phonebookengines/contactsmodel/cntplsql/src/cntmetadataoperation.cpp
changeset 24 0ba2181d7c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/cntmetadataoperation.cpp	Fri Mar 19 09:27:18 2010 +0200
@@ -0,0 +1,281 @@
+/*
+* Copyright (c) 2005-2009 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: 
+*
+*/
+
+//#include <columbo.h>
+#include <cntitem.h>
+#include <cntfldst.h>
+
+#include "cntmetadataoperation.h"
+
+CCntMetadataOperation::CCntMetadataOperation(RColumboSession& aSession) 
+: CActive(EPriorityStandard), iSession(aSession), iContactId(-1)
+    {
+    }
+
+/**
+ * Construct a new metadata operation object. Note that this object will destroy
+ * itself after either save or delete operations have been called.
+ * 
+ * The new object will be left on the cleanup stack.
+ * 
+ * @param aSession Session with the metadata service.
+ * @return The new metadata operation instance.
+ */
+CCntMetadataOperation* CCntMetadataOperation::NewLC(RColumboSession& aSession)
+    {
+    CCntMetadataOperation* self = new (ELeave) CCntMetadataOperation(aSession);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+/**
+ * Construct a new metadata operation object. Note that this object will destroy
+ * itself after either save or delete operations have been called.
+ * 
+ * @param aSession Session with the metadata service.
+ * @return The new metadata operation instance.
+ */
+CCntMetadataOperation* CCntMetadataOperation::NewL(RColumboSession& aSession)
+    {
+    CCntMetadataOperation* self = CCntMetadataOperation::NewLC(aSession);
+    CleanupStack::Pop();
+    return self;
+    }
+
+/**
+ * Note: upon construction, the active object is set active and waiting
+ * for a completion event to destroy itself.
+ */
+void CCntMetadataOperation::ConstructL()
+    {
+    CActiveScheduler::Add(this);
+    }
+
+CCntMetadataOperation::~CCntMetadataOperation()
+    {
+    // (iSession is not owned)
+    delete iDocument;
+    delete iKey;
+    }
+
+/**
+ * The DoCancel() function will only delete the object in production builds.
+ * If __PROFILE_DEBUG__ is defined in the persistence layer MMP file,
+ * error codes will be logged should they occur.
+ */
+void CCntMetadataOperation::DoCancel()
+    {
+    // Log that the operation is cancelled.
+#ifdef __PROFILE_DEBUG__
+    _LIT(KCancelFormat, "CCntMetadataOperation::DoCancel(): Operation Cancelled: Contact ID = %d");
+    RDebug::Print(KCancelFormat(), iContactId);
+#endif
+    
+    // Self destruct - operation cancelled.
+    delete this;
+    }
+
+/**
+ * The RunL() function will only delete the object in production builds.
+ * If __PROFILE_DEBUG__ is defined in the persistence layer MMP file,
+ * error codes will be logged should they occur.
+ */
+void CCntMetadataOperation::RunL()
+    {
+#ifdef __PROFILE_DEBUG__
+    if (iStatus.Int() != KErrNone)
+        {
+        _LIT(KErrorFormat, "CCntMetadataOperation::RunL(): Operation failed [Contact ID = %d] Error = %d");
+        RDebug::Print(KErrorFormat(), iContactId, iStatus.Int());
+        }
+    else
+        {
+        _LIT(KErrorFormat, "CCntMetadataOperation::RunL(): Operation complete [Contact ID = %d]");
+        RDebug::Print(KErrorFormat(), iContactId);
+        }
+#endif // __PROFILE_DEBUG__
+    
+    // Self destruct - operation complete.
+    delete this;
+    }
+
+TInt CCntMetadataOperation::RunError(TInt aError)
+    {
+    // RunL() doesn't really leave, this should never happen.
+    // Log but do nothing.
+#ifdef __PROFILE_DEBUG__
+    _LIT(KRunErrorLog, "CCntMetadataOperation::RunError(): aError = %d");
+    RDebug::Print(KRunErrorLog(), aError);
+#endif // __PROFILE_DEBUG__
+    return aError;
+    }
+
+/**
+ * Save the contact @a aContact in the metadata service. If there is
+ * already a contact entry with this ID, it will be updated. Otherwise,
+ * a new contact metadata entry is added.
+ * 
+ * The metadata operation object will be destroyed when the operation
+ * completes. Do not attempt to use this object after calling.
+ * 
+ * @param aContact The contact item to index for metadata.
+ */
+void CCntMetadataOperation::SaveContactLD(const CContactItem& aContact)
+    {
+    // For logging purposes
+    iContactId = aContact.Id();
+    
+    // Create a new generic metadata object for this contact item.
+    if (iDocument)
+        {
+        delete iDocument;
+        iDocument = NULL;
+        }
+    iDocument = DocumentFromContactL(aContact);
+    iDocument->Store(iSession, iStatus);
+    SetActive();
+    }
+
+/**
+ * Remove the contact described by @a aContactId from the metadata store.
+ * 
+ * The metadata operation object will be destroyed when the operation
+ * completes. Do not attempt to use this object after calling.
+ * 
+ * @param aContactId The contact to be removed from the metadata service
+ */
+void CCntMetadataOperation::DeleteContactLD(TInt aContactId)
+    {
+    // For logging purposes
+    iContactId = aContactId;
+    
+    // Get the key and delete the document
+    if (iKey)
+		{
+		delete iKey;
+		iKey = NULL;
+		}
+    HBufC* iKey = ContactMetadataKeyLC(aContactId);
+    CleanupStack::Pop();
+    
+    iSession.DeleteDocument(*iKey, iStatus);
+    SetActive();
+    }
+
+/**
+ * Construct a new generic metadata object to represent a contact item.
+ * 
+ * @param aContact The contact item to encode as a generic metadata object.
+ * @return The newly constructed metadata object instance.
+ */
+CMetadataDocument* CCntMetadataOperation::DocumentFromContactL(const CContactItem& aContact)
+    {
+    CMetadataDocument* document = CMetadataDocument::NewLC();
+    
+    // Assign a unique key for cntmodel purposes
+    HBufC* key = ContactMetadataKeyLC(aContact.Id());
+    document->SetUserKeyL(*key);
+    CleanupStack::PopAndDestroy(key);
+    
+    // Iterate through fields, and produce a metadata string for this contact
+    CContactItemFieldSet& fields = aContact.CardFields();
+    const TInt KFieldCount(fields.Count());
+    
+    if (KFieldCount > 0)
+        {
+        // Find out how much space we need for the metadata buffer
+        TInt bufferLength(0);
+        for(TInt i(0); i < KFieldCount; ++i)
+            {
+            CContactItemField& field = fields[i];
+            if (field.StorageType() != KStorageTypeText)
+                {
+                // Can only index text, no point if text is 0 length
+                continue;
+                }
+            
+            // No point in indexing 0 length data
+            TInt fieldLength = field.TextStorage()->Text().Length();
+            if (fieldLength == 0)
+                {
+                continue;
+                }
+            
+            // Add field length plus the length of a space to
+            // seperate it from the next field
+            bufferLength += (fieldLength + 1);
+            }
+        
+        // Allocate a buffer and add all the fields to it
+        HBufC* metadata = HBufC::NewLC(bufferLength);
+        TPtr bufferPtr = metadata->Des();
+        
+        for(TInt i(0); i < KFieldCount; ++i)
+            {
+            CContactItemField& field = fields[i];
+            if (field.StorageType() != KStorageTypeText)
+                {
+                // Can only index text
+                continue;
+                }
+            
+            // No point in indexing 0 length data
+            TInt fieldLength = field.TextStorage()->Text().Length();
+            if (fieldLength == 0)
+                {
+                continue;
+                }
+            
+            TPtrC fieldContent = field.TextStorage()->Text();
+            bufferPtr.Append(fieldContent);
+
+            // Add a space as a seperator
+            _LIT(KSpace, " ");
+            bufferPtr.Append(KSpace);
+            }
+
+        // Add the metadta to the generic document
+        document->SetMetadataL(*metadata);
+        CleanupStack::PopAndDestroy(metadata);
+        }
+    
+    CleanupStack::Pop(document);
+    return document;
+    }
+
+/**
+ * Generate an RDNS style key to identify the metadata object for cntmodel purposes.
+ * 
+ * @param aContactId The contact model assigned contact ID.
+ * @return A descriptor containing the new unique identifier for the document object.
+ */
+HBufC* CCntMetadataOperation::ContactMetadataKeyLC(TInt aContactId)
+    {
+    // Key format for cntmodel entries in the metadata service
+    _LIT(KKeyFormat, "com.nokia.contact.id.%d");
+    
+    // Allocate a big enough buffer for just the key format with
+    // an integer added to the end
+    HBufC* key = HBufC::NewLC(KKeyFormat().Length() + 32);
+    TPtr keyPtr = key->Des();
+    keyPtr.AppendFormat(KKeyFormat(), aContactId);
+    
+    // Leaving key on the cleanup stack
+    return key;
+    }
+