phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkVCardCompactBCardImporter.cpp
changeset 0 e686773b3f54
child 68 9da50d567e3c
--- /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