--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkVCardCompactBCardImporter.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,592 @@
+/*
+* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Virtual Phonebook VCard compact BCard importer
+*
+*/
+
+
+
+// System includes
+#include <versit.h>
+
+#include "CVPbkVCardData.h"
+#include "CVPbkVCardCompactBCardImporter.h"
+#include "VPbkVCardEngError.h"
+#include "CVPbkVCardFieldTypeProperty.h"
+#include <VPbkEng.rsg>
+
+// From Virtual Phonebook engine
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkFieldType.h>
+#include <MVPbkSingleContactOperationObserver.h>
+#include <MVPbkStoreContactField.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactCopyPolicy.h>
+#include <MVPbkContactOperationBase.h>
+
+
+#ifdef _DEBUG
+using namespace VPbkVCardEngError;
+#endif // _DEBUG
+
+namespace
+ {
+ enum TVPbkBCardImporterState
+ {
+ EGetLine,
+ EStartTitleCopy,
+ EAddAddress,
+ EStop
+ };
+
+ _LIT(KBusinessCardText, "Business Card"); // Business card signature
+ _LIT(KCloseParenthesis, ")");
+ _LIT(KTelText, "tel ");
+ _LIT(KFaxText, "fax ");
+ _LIT(KSeparatorText, ", ");
+ const TText KOpenParenthesis = '(';
+ // Assume compact business card is corrupted if single field length
+ // exceeds 200 bytes. This value is not officially specified anywhere.
+ const TInt KBufferSize = 200;
+ const TInt KStartPosition = 4;
+ const TInt KLabelStartPosition = 5;
+ const TInt KLabelValueDelimiterLength = 2;
+ const TInt KGranularity( 2 );
+
+ // Comapct business card fixed field line numbers.
+ enum TVPbkCBCFieldLines
+ {
+ ECBCSignatureLine = 1,
+ ECBCNameLine,
+ ECBCCompanyLine,
+ ECBCTitleLine
+ };
+ } // namespace
+
+CVPbkVCardCompactBCardImporter::CVPbkVCardCompactBCardImporter(
+ RPointerArray<MVPbkStoreContact>& aImportedContacts,
+ MVPbkContactStore& aTargetStore,
+ RReadStream &aSourceStream,
+ CVPbkVCardData& aData )
+ : CActive( EPriorityStandard ),
+ iImportedContacts( aImportedContacts ),
+ iTargetStore(aTargetStore),
+ iData( aData ),
+ iSource( aSourceStream )
+ {
+ }
+
+CVPbkVCardCompactBCardImporter* CVPbkVCardCompactBCardImporter::NewL(
+ RPointerArray<MVPbkStoreContact>& aImportedContacts,
+ MVPbkContactStore& aTargetStore,
+ RReadStream &aSourceStream,
+ CVPbkVCardData& aData )
+ {
+ CVPbkVCardCompactBCardImporter* self = new (ELeave)
+ CVPbkVCardCompactBCardImporter(
+ aImportedContacts,
+ aTargetStore,
+ aSourceStream,
+ aData );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+void CVPbkVCardCompactBCardImporter::ConstructL()
+ {
+ CActiveScheduler::Add(this);
+ iAddressArray = new( ELeave ) CDesCArrayFlat( KGranularity );
+ iCopyPolicy = &iData.CopyPolicyL( iTargetStore.StoreProperties().Uri() );
+ }
+
+CVPbkVCardCompactBCardImporter::~CVPbkVCardCompactBCardImporter()
+ {
+ Cancel();
+ delete iAddToFieldOperation;
+ delete iCurContact;
+ delete iAddressArray;
+ delete iValue;
+ delete iLabel;
+ delete iLine;
+ }
+
+void CVPbkVCardCompactBCardImporter::StartL()
+ {
+ iCurContact = iTargetStore.CreateNewContactLC();
+ CleanupStack::Pop();
+ iState = EGetLine;
+ IssueRequest();
+ }
+
+void CVPbkVCardCompactBCardImporter::SetObserver(
+ MVPbkImportOperationObserver& aObserver )
+ {
+ iObserver = &aObserver;
+ }
+
+void CVPbkVCardCompactBCardImporter::RunL()
+ {
+ switch (iState)
+ {
+ case EGetLine:
+ {
+ if (GetLineL())
+ {
+ ParseLineL();
+ }
+ break;
+ }
+ case EAddAddress:
+ {
+ AddAddressL();
+ break;
+ }
+ case EStartTitleCopy:
+ {
+ StartTitleCopyL();
+ break;
+ }
+ case EStop:
+ {
+ iObserver->ContactsImportingCompleted();
+ break;
+ }
+ default:
+ {
+ // Do nothing
+ break;
+ }
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::DoCancel()
+ {
+ delete iAddToFieldOperation;
+ iAddToFieldOperation = NULL;
+ }
+
+TInt CVPbkVCardCompactBCardImporter::RunError(TInt aError)
+ {
+ iObserver->ContactImportingFailed( aError );
+ return KErrNone;
+ }
+
+void CVPbkVCardCompactBCardImporter::FieldAddedToContact(
+ MVPbkContactOperationBase& aOperation)
+ {
+ if ( &aOperation == iAddToFieldOperation )
+ {
+ delete iAddToFieldOperation;
+ iAddToFieldOperation = NULL;
+ IssueRequest();
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::FieldAddingFailed(
+ MVPbkContactOperationBase& aOperation, TInt aError)
+ {
+ if ( &aOperation == iAddToFieldOperation )
+ {
+ delete iAddToFieldOperation;
+ iAddToFieldOperation = NULL;
+ if (aError == KErrNotSupported )
+ {
+ // Target contact didn't support field -> continue
+ IssueRequest();
+ }
+ else if ( aError == KErrOverflow )
+ {
+ // Target contact is full of that field
+ TRAPD( res, HandleContactSwitchL() );
+ HandleError( res );
+ }
+ else
+ {
+ iObserver->ContactImportingFailed( aError );
+ }
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::FieldsCopiedToContact(
+ MVPbkContactOperationBase& /*aOperation*/)
+ {
+ ++iTargetContactIndex;
+ if ( iTargetContactIndex >= iImportedContacts.Count() )
+ {
+ iObserver->ContactsImported();
+ }
+ else
+ {
+ TRAPD( res, CopyTitleL() );
+ HandleError( res );
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::FieldsCopyFailed(
+ MVPbkContactOperationBase& /*aOperation*/,
+ TInt aError)
+ {
+ HandleError( aError );
+ }
+
+void CVPbkVCardCompactBCardImporter::IssueRequest()
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+TBool CVPbkVCardCompactBCardImporter::GetLineL()
+ {
+ delete iLine;
+ iLine = NULL;
+ iLine = HBufC::NewL( KBufferSize );
+ TPtr line = iLine->Des();
+
+ TBool result = EFalse;
+ TInt retVal( GetLineFromStreamL( line, iSource ) );
+ if ( retVal == KErrNone || retVal == KErrEof )
+ {
+ if(line.Length() > 0)
+ {
+ ++iLineCount;
+ result = ETrue;
+ }
+ else
+ {
+ iState = EStop;
+ IssueRequest();
+ }
+
+ }
+ if(retVal == KErrEof && line.Length() > 0 )
+ {
+ iState = EAddAddress;
+ }
+
+ return result;
+ }
+
+void CVPbkVCardCompactBCardImporter::ParseLineL()
+ {
+ TPtr line = iLine->Des();
+ TInt resId( ResolveFieldTypeResIdL( line ) );
+
+ if ( resId == KErrNotFound )
+ {
+ IssueRequest();
+ }
+ else if ( resId == R_VPBK_FIELD_TYPE_LANDPHONEGEN ||
+ resId == R_VPBK_FIELD_TYPE_FAXNUMBERGEN )
+ {
+ // Asynchronous
+ ValueAndLabelToBufL( line, resId );
+ }
+ else if ( resId == R_VPBK_FIELD_TYPE_ADDRLABELGEN )
+ {
+ // Synchronous
+ ValueToArrayL( line );
+ IssueRequest();
+ }
+ else
+ {
+ // Asynchronous
+ ValueToBufL( line, resId );
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::ValueToBufL(
+ const TDesC& aBuffer, TInt aResId )
+ {
+ const MVPbkFieldType* fieldType = FindFieldTypeL( aResId );
+ __ASSERT_DEBUG( fieldType,
+ VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
+
+ AddFieldWithValueL( *fieldType, aBuffer, NULL );
+ }
+
+void CVPbkVCardCompactBCardImporter::ValueToArrayL( const TDesC& aBuffer )
+ {
+ // Address is saved after all other fields have been saved
+ iAddressArray->AppendL( aBuffer );
+
+ if( iValueLength )
+ {
+ iValueLength += KSeparatorText().Length();
+ }
+
+ iValueLength += aBuffer.Length();
+ }
+
+void CVPbkVCardCompactBCardImporter::ValueAndLabelToBufL(
+ const TDesC& aBuffer, TInt aResId )
+ {
+ const MVPbkFieldType* fieldType = FindFieldTypeL( aResId );
+ __ASSERT_DEBUG( fieldType,
+ VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
+
+ // Read tel num label
+ TInt position( KStartPosition );
+
+ delete iLabel;
+ iLabel = NULL;
+ if( aBuffer[KStartPosition] == KOpenParenthesis )
+ {
+ position = aBuffer.Find( KCloseParenthesis );
+ if( position == KErrNotFound )
+ {
+ return;
+ }
+ iLabel = HBufC::NewL( position - KStartPosition );
+ TPtr writebuf = iLabel->Des();
+ writebuf = KNullDesC;
+ for( TInt i = KLabelStartPosition; i<position; i++ )
+ {
+ writebuf.Append( aBuffer[i] );
+ }
+ // Jump few characters
+ position += KLabelValueDelimiterLength;
+ }
+
+ // Read value
+ delete iValue;
+ iValue = NULL;
+ iValue = HBufC::NewL( aBuffer.Length() - position );
+ TPtr writebuf = iValue->Des();
+ writebuf = KNullDesC;
+ for( TInt i = position; i < aBuffer.Length(); i++ )
+ {
+ writebuf.Append( aBuffer[i] );
+ }
+
+ AddFieldWithValueL( *fieldType, *iValue, iLabel );
+ }
+
+void CVPbkVCardCompactBCardImporter::AddAddressL()
+ {
+ if ( iAddressArray->Count() > 0 )
+ {
+ // Then concatenate them with commas into one string
+ // and use that as field value.
+ HBufC* fielddata = HBufC::NewLC( iValueLength );
+ TPtr writebuf = fielddata->Des();
+ writebuf = KNullDesC;
+ TInt count = iAddressArray->Count();
+ for( TInt i = 0; i < count; ++i )
+ {
+ if( i )
+ {
+ writebuf.Append( KSeparatorText );
+ }
+ writebuf.Append( iAddressArray->MdcaPoint( i ) );
+ }
+
+ const MVPbkFieldType* fieldType = FindFieldTypeL( R_VPBK_FIELD_TYPE_ADDRLABELGEN );
+ __ASSERT_DEBUG( fieldType,
+ VPbkVCardEngError::Panic( VPbkVCardEngError::ENullFieldType ) );
+
+ AddFieldWithValueL( *fieldType, *fielddata, NULL );
+ CleanupStack::PopAndDestroy( fielddata );
+ }
+ else
+ {
+ IssueRequest();
+ }
+
+ // Address is the last field so continue with titles after address
+ // has been added, or not added
+ iState = EStartTitleCopy;
+ }
+
+TInt CVPbkVCardCompactBCardImporter::ResolveFieldTypeResIdL( const TDesC& aBuffer )
+ {
+ TInt resId( KErrNotFound );
+ switch ( iLineCount )
+ {
+ case ECBCSignatureLine:
+ {
+ if ( aBuffer.Match( KBusinessCardText() ) == KErrNotFound )
+ {
+ User::Leave( KErrNotSupported );
+ }
+ return resId;
+ }
+
+ case ECBCNameLine: // Name
+ {
+ resId = R_VPBK_FIELD_TYPE_LASTNAME;
+ break;
+ }
+
+ case ECBCCompanyLine: // Company name
+ {
+ resId = R_VPBK_FIELD_TYPE_COMPANYNAME;
+ break;
+ }
+
+ case ECBCTitleLine: // Title
+ {
+ resId = R_VPBK_FIELD_TYPE_JOBTITLE;
+ break;
+ }
+ }
+
+ if ( resId == KErrNotFound ) // Tel numbers
+ {
+ if ( aBuffer.Find( KTelText ) >= 0 )
+ {
+ resId = R_VPBK_FIELD_TYPE_LANDPHONEGEN;
+ }
+
+ else if ( aBuffer.Find( KFaxText ) >= 0 )
+ {
+ resId = R_VPBK_FIELD_TYPE_FAXNUMBERGEN;
+ }
+ }
+ if ( !iEMailFetchedFlag && resId == KErrNotFound )
+ {
+ resId = R_VPBK_FIELD_TYPE_EMAILGEN; // Email address
+ iEMailFetchedFlag = ETrue;
+ }
+
+ if ( resId == KErrNotFound )// Postal address
+ {
+ resId = R_VPBK_FIELD_TYPE_ADDRLABELGEN;
+ }
+
+ return resId;
+ }
+
+void CVPbkVCardCompactBCardImporter::AddFieldWithValueL(
+ const MVPbkFieldType& aFieldType, const TDesC& aValue, HBufC* aLabel )
+ {
+ __ASSERT_DEBUG( !iAddToFieldOperation,
+ VPbkVCardEngError::Panic(
+ VPbkVCardEngError::EAddToFieldOperationAlreadyExists ) );
+
+ iAddToFieldOperation = iCopyPolicy->AddFieldToContactL(
+ *iCurContact, aFieldType, aValue, aLabel, NULL, *this);
+ }
+
+void CVPbkVCardCompactBCardImporter::StartTitleCopyL()
+ {
+ MoveCurrentContactToImportsL();
+
+ // If vcard was split to multiple contacts then copy
+ // title fields from the first imported contact to the other contacts.
+ const TInt oneContactImported = 1;
+ if ( iImportedContacts.Count() <= oneContactImported )
+ {
+ iObserver->ContactsImported();
+ }
+ else
+ {
+ iTargetContactIndex = oneContactImported;
+ CopyTitleL();
+ }
+ }
+
+const MVPbkFieldType* CVPbkVCardCompactBCardImporter::FindFieldTypeL(
+ TInt aFieldIndex )
+ {
+ return iData.SupportedFieldTypes().Find( aFieldIndex );
+ }
+
+TInt CVPbkVCardCompactBCardImporter::GetByteFromStream(
+ TInt8& aByte, RReadStream& aSourceStream)
+ {
+ TRAPD(err, aByte = aSourceStream.ReadInt8L());
+ return err;
+ }
+
+TInt CVPbkVCardCompactBCardImporter::GetLineFromStreamL(
+ TDes& aBuf, RReadStream& aSourceStream)
+ {
+ aBuf.SetLength(0);
+ TInt8 byte=0;
+ TInt retVal( KErrNone );
+ while( ( retVal = GetByteFromStream(byte, aSourceStream) ) == KErrNone)
+ {
+ if(byte == EKeyLineFeed)
+ {
+ break;
+ }
+ if(byte != EKeyEnter)
+ {
+ if (aBuf.Length() < aBuf.MaxLength())
+ {
+ aBuf.Append(byte);
+ }
+ else
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ }
+
+ return retVal;
+ }
+
+void CVPbkVCardCompactBCardImporter::HandleContactSwitchL()
+ {
+ // Current contact is full -> Create a new contact and
+ // add the same line to that one.
+ MoveCurrentContactToImportsL();
+ iCurContact = iTargetStore.CreateNewContactLC();
+ CleanupStack::Pop();
+ if ( iLine && iLine->Length() > 0 )
+ {
+ // Parse same line again
+ ParseLineL();
+ }
+ else
+ {
+ // End of file -> continue with address
+ AddAddressL();
+ }
+ }
+
+void CVPbkVCardCompactBCardImporter::CopyTitleL()
+ {
+ delete iAddToFieldOperation;
+ iAddToFieldOperation = NULL;
+ iAddToFieldOperation = iCopyPolicy->CopyTitleFieldsL(
+ *iImportedContacts[0],
+ *iImportedContacts[iTargetContactIndex],
+ *this );
+ }
+
+void CVPbkVCardCompactBCardImporter::MoveCurrentContactToImportsL()
+ {
+ iImportedContacts.AppendL( iCurContact );
+ iCurContact = NULL;
+ }
+
+void CVPbkVCardCompactBCardImporter::HandleError( TInt aError )
+ {
+ if ( aError != KErrNone )
+ {
+ iObserver->ContactImportingFailed( aError );
+ }
+ }
+ TBool CVPbkVCardCompactBCardImporter::IsOwncard()
+ {
+ return EFalse;
+ }
+
+// End of file