PECengine/AttributeLibrary2/SrcTransactions/CPEngFetchProcessor.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PECengine/AttributeLibrary2/SrcTransactions/CPEngFetchProcessor.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,529 @@
+/*
+* Copyright (c) 2005 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:  Attribute fetch processor.
+*
+*/
+
+// INCLUDE FILES
+#include "CPEngFetchProcessor.h"
+#include "CPEngAttributeTypeStack.h"
+#include "CPEngTransactionStatus.h"
+#include "PEngAddressUtils.h"
+#include "MPEngPresenceAttrManager.h"
+#include "MPEngPresenceAdvancedAttrModel2.h"
+
+#include "MPEngXMLSerializer.h"
+#include "MPEngXMLParser.h"
+#include "PEngWVPresenceAttributes2.h"
+#include "PEngAttrModelHelper.h"
+
+#include "PresenceDebugPrint.h"
+
+#include <PEngWVPresenceErrors2.h>
+#include <E32Std.h>
+
+
+
+
+// CONSTANTS
+/**
+ * Granularity for array of fetched presence ids.
+ * Usually there is just few fetched presence id's
+ * at time.
+ */
+const TInt KPEngFetchPresIdGranurality = 5;
+
+
+
+// ========================== EXPORTED FUNCTIONS ===============================
+// -----------------------------------------------------------------------------
+// CreateAttrFetchProcessorL()
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MPEngAttrFetchProcessor* CreateAttrFetchProcessorL(
+    MPEngPresenceAttrManager& aAttrManager,
+    const MDesCArray& aFetchedPresenceIds,
+    const TArray< TUint32 > aFetchedAttributes,
+    const TDesC& aDomain,
+    TInt aTransactionOperation,
+    TPEngWVCspVersion aCspVersion )
+    {
+    return CPEngFetchProcessor::NewL( aAttrManager,
+                                      aFetchedPresenceIds,
+                                      aFetchedAttributes,
+                                      aDomain,
+                                      aTransactionOperation,
+                                      aCspVersion );
+    }
+
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::NewL()
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPEngFetchProcessor* CPEngFetchProcessor::NewL( MPEngPresenceAttrManager& aAttrManager,
+                                                const MDesCArray& aFetchedPresenceIds,
+                                                const TArray< TUint32 > aFetchedAttributes,
+                                                const TDesC& aDomain,
+                                                TInt aTransactionOperation,
+                                                TPEngWVCspVersion aCspVersion )
+    {
+    CPEngFetchProcessor* self = new ( ELeave ) CPEngFetchProcessor(
+        aAttrManager,
+        aTransactionOperation,
+        aCspVersion );
+
+    CleanupStack::PushL( self );
+    self->ConstructL( aFetchedPresenceIds, aFetchedAttributes, aDomain );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// Destructor
+CPEngFetchProcessor::~CPEngFetchProcessor()
+    {
+    iFetchedPresenceIds.Reset();
+
+    delete iFechedAttributeTypes;
+    delete iDomain;
+    delete iXmlParser;
+
+    iPresenceBlocks.Reset();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::CPEngFetchProcessor
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CPEngFetchProcessor::CPEngFetchProcessor( MPEngPresenceAttrManager& aAttrManager,
+                                          TInt aTransactionOperation,
+                                          TPEngWVCspVersion aCspVersion )
+        : iAttributeManager( aAttrManager ),
+        iTransactionOperation( aTransactionOperation ),
+        iCspVersion( aCspVersion ),
+        iFetchedPresenceIds( KPEngFetchPresIdGranurality ),
+        iPresenceBlocks( KPEngFetchPresIdGranurality )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::ConstructL()
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::ConstructL( const MDesCArray& aFetchedPresenceIds,
+                                      const TArray< TUint32 > aFetchedAttributes,
+                                      const TDesC& aDomain )
+    {
+    __ASSERT_ALWAYS( aFetchedPresenceIds.MdcaCount() > 0, User::Leave( KErrArgument ) );
+    __ASSERT_ALWAYS( aFetchedAttributes.Count() > 0, User::Leave( KErrArgument ) );
+
+    iXmlParser = CreateXMLParserL();
+    iDomain = aDomain.AllocL();
+
+    const TInt presenceIdCount = aFetchedPresenceIds.MdcaCount();
+    for ( TInt ix = 0; ix < presenceIdCount; ix++ )
+        {
+        //Allow one presence ID only once
+        iFetchedPresenceIds.InsertIsqL( aFetchedPresenceIds.MdcaPoint( ix ),
+                                        ECmpNormal );
+        }
+
+
+    //Gather attribute names & name spaces
+    //This will also validate that attributes are valid network attributes
+    iFechedAttributeTypes = CPEngAttributeTypeStack::NewL();
+    iFechedAttributeTypes->PushAttributesL( aFetchedAttributes,
+                                            iAttributeManager );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::GenerateRequestL()
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::GenerateRequestL( TDes8& aSendBuffer )
+    {
+    aSendBuffer.Zero();
+    MPEngXMLSerializer* serialize = CreateXmlSerializerLC( aSendBuffer );
+    GenerateRequestL( *serialize,
+                      iFetchedPresenceIds,
+                      *iFechedAttributeTypes,
+                      iCspVersion );
+
+    CleanupStack::PopAndDestroy(); //serialize
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::InitResponseProcessingL()
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::InitResponseProcessingL(
+    const TDesC8& aResponse,
+    RPointerArray< MPEngPresenceAttrModel2 >& aResultModels,
+    MPEngAdvTransactionStatus2& aResultStatus )
+
+
+    {
+    iPresenceBlocks.Reset();
+    iFetchedModels = &aResultModels;
+    iTransactionStatus = &aResultStatus;
+
+
+    // If there isn't status primitive or the presence response,
+    // indicate the corrupted response to client
+    if ( !iXmlParser->DecodeL( aResponse, KStatusTag, ETrue, 3 ) &&
+         !iXmlParser->DecodeL( aResponse, KGetPresenceResponse, ETrue ) )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+
+    //Is there something to parse ?
+    if ( CheckResultFromFromResponseL( aResponse,
+                                       *iDomain,
+                                       iTransactionOperation,
+                                       *iXmlParser,
+                                       *iTransactionStatus,
+                                       iFetchedPresenceIds
+                                     ) )
+        {
+        //Split presence blocks from response to array
+        LocatePresenceBlocksFromResponseL( aResponse,
+                                           *iXmlParser,
+                                           iPresenceBlocks );
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::ProcessStepL()
+// -----------------------------------------------------------------------------
+//
+TBool CPEngFetchProcessor::ProcessStepL()
+    {
+    if ( iPresenceBlocks.Count() > 0 )
+        {
+        //Handle the first block
+        ParseModelsFromBlockL( iPresenceBlocks[ 0 ],
+                               iAttributeManager,
+                               *iXmlParser,
+                               iFetchedPresenceIds,
+                               *iDomain,
+                               *iFechedAttributeTypes,
+                               *iFetchedModels,
+                               iTransactionOperation );
+        //Remove the first block
+        iPresenceBlocks.Delete( 0 );
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::GenerateRequestL()
+// Parsing helper
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::GenerateRequestL(
+    MPEngXMLSerializer& aSerializer,
+    const CDesC16ArraySeg& aFetchedPresenceIds,
+    const CPEngAttributeTypeStack& aFechedAttributeTypes,
+    TPEngWVCspVersion aCspVersion )
+    {
+    TPtrC8 transactionContentNS( KTransactionContentNS );
+    TPtrC8 presenceSubListNS( KPresenceSubListAttributesNS );
+
+    if ( aCspVersion == EWVCspV12 )
+        {
+        transactionContentNS.Set( KTransactionContentNS_CSP12 );
+        presenceSubListNS.Set( KPresenceSubListAttributesNS_CSP12 );
+        }
+
+    const TInt presenceIdCount( aFetchedPresenceIds.Count() );
+    aSerializer.StartTagL( KTransactionContent );
+    aSerializer.AttributeL( KXmlXmlns, transactionContentNS );
+
+    aSerializer.StartTagL( KGetPresenceRequest );
+
+    //Generate first requested presence ID's
+    TInt index = 0;
+    for ( index = 0; index < presenceIdCount; index++ )
+        {
+        aSerializer.StartTagL( KUser );
+        aSerializer.StartTagL( KUserIDXMLTag );
+            {
+            aSerializer.WvAddressL( aFetchedPresenceIds[ index ] );
+            }
+        aSerializer.EndTagL( KUserIDXMLTag );
+        aSerializer.EndTagL( KUser );
+        }
+
+
+    //And then requested attribute ID's
+    //When engine starts support extension attributes,
+    //this must be changed to use properly the name spaces.
+    aSerializer.StartTagL( KPresenceSubList );
+    aSerializer.AttributeL( KXmlXmlns, presenceSubListNS );
+
+    TInt attributeCount( aFechedAttributeTypes.TypeCount() );
+    for ( index = 0; index < attributeCount; index++ )
+        {
+        aSerializer.StartTagL( aFechedAttributeTypes.Name( index ) );
+        aSerializer.EndTagL( aFechedAttributeTypes.Name( index ) );
+        }
+
+    aSerializer.EndTagL( KPresenceSubList );
+
+    aSerializer.EndTagL( KGetPresenceRequest );
+    aSerializer.EndTagL( KTransactionContent );
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::CheckResultFromFromResponseL()
+// Parsing helper
+// -----------------------------------------------------------------------------
+//
+TBool CPEngFetchProcessor::CheckResultFromFromResponseL(
+    const TDesC8& aResponse,
+    const TDesC& aDomain,
+    TInt aTransactionOperation,
+    MPEngXMLParser& aParser,
+    MPEngAdvTransactionStatus2& aTransactionStatus,
+    CDesC16Array& aRequestedPresenceIds )
+    {
+    //Get the result structure from response
+    aParser.ParseResultL( aResponse,
+                          aTransactionOperation,
+                          aTransactionStatus );
+
+    //Filter presence id's according the network server response status
+    //If all requested presence id's were unknown, no need to do further
+    //processing. In this case add all requested presence id's
+    //as detailed result.
+    if ( aTransactionStatus.Status() == KPEngNwErrUnknownUser )
+        {
+        TInt presIdCount = aRequestedPresenceIds.Count();
+        for ( TInt presIdIx( 0 ); presIdIx < presIdCount; presIdIx++ )
+            {
+            TPtrC presenceId( aRequestedPresenceIds[ presIdIx ] );
+            aTransactionStatus.AddDetailedResultL( aTransactionOperation,
+                                                   KPEngNwErrUnknownUser,
+                                                   NULL,
+                                                   &presenceId,
+                                                   NULL,
+                                                   NULL );
+            }
+
+        return EFalse;
+        }
+
+    //If partial failure, remove unknown presence id's
+    if ( aTransactionStatus.Status() == KPEngNwErrPartiallySuccessful )
+        {
+        const TInt detailedResults = aTransactionStatus.DetailedResultCount();
+        for ( TInt dResultIx( 0 ); dResultIx < detailedResults; dResultIx++ )
+            {
+            const MPEngDetailedResultEntry2& dEntry =
+                aTransactionStatus.DetailedResult( dResultIx );
+            TPtrC unknownPresenceId( NULL, 0 );
+            if ( dEntry.GetDetailedDesc( unknownPresenceId,
+                                         EPEngDTPresenceID ) == KErrNone )
+                {
+                //there was a presence id reported in detailed result
+                //assume that it is failed and try remove it from fetched presences
+                TInt index =
+                    PEngAddressUtils::FindWVAddressF( unknownPresenceId,
+                                                      aRequestedPresenceIds,
+                                                      aDomain,
+                                                      PEngAddressUtils::EMatchToUniqueId );
+                if ( index != KErrNotFound )
+                    {
+                    aRequestedPresenceIds.Delete( index );
+                    }
+
+                //If there is some requested user ID reported in response as unknown,
+                //but its locating & remove from requested ID's array fails
+                //==> no problem, only those users models are anyway returned
+                //to client, which are found from response.
+                }
+            }
+        }
+
+    return ETrue;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::LocatePresenceBlocksFromResponseL()
+// Parsing helper
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::LocatePresenceBlocksFromResponseL(
+    const TDesC8& aResponse,
+    MPEngXMLParser& aParser,
+    CDesC8Array& aPresenceBlocks )
+    {
+    //locate the presence data blocks
+    if ( aParser.DecodeL( aResponse, KPresenceXMLTag, ETrue ) )
+        {
+        //place found presence data blocks to an array
+        TInt foundPresencesCount = aParser.Count();
+        for ( TInt blockIndex = 0; blockIndex < foundPresencesCount; blockIndex++ )
+            {
+            aPresenceBlocks.AppendL( aParser.ResultL( blockIndex ) );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngFetchProcessor::ParseModelsFromBlockL()
+// Parsing helper
+// -----------------------------------------------------------------------------
+//
+void CPEngFetchProcessor::ParseModelsFromBlockL(
+    const TDesC8& aPresenceBlock,
+    MPEngPresenceAttrManager& aAttrManager,
+    MPEngXMLParser& aParser,
+    CDesC16Array& aFetchedPresenceIds,
+    const TDesC& aDomain,
+    const CPEngAttributeTypeStack& aAttributeTypes,
+    RPointerArray<MPEngPresenceAttrModel2>& aResultModels,
+    TInt aOperation )
+    {
+    if ( aParser.DecodeL( aPresenceBlock, KUserIDXMLTag, EFalse ) )
+        {
+        //There is a presence id => unescape the id
+        HBufC* presIdBuf = aParser.ResultAsWVAddressL();
+        CleanupStack::PushL( presIdBuf );
+
+        //Try get the presence id as it was really requested
+        TInt presenceIdIndex = PEngAddressUtils::FindWVAddressF( *presIdBuf,
+                                                                 aFetchedPresenceIds,
+                                                                 aDomain,
+                                                                 PEngAddressUtils::EMatchToUniqueId );
+        if ( presenceIdIndex != KErrNotFound )
+            {
+            //There is client requested presence ID for this presence block
+            //Use the client given ID as model ID.
+            //If not able to match to client given id, actual id from presence block is used
+            TPtrC clientPresenceId( aFetchedPresenceIds[ presenceIdIndex ] );
+            HBufC* clientPresenceIdBuf = clientPresenceId.AllocL();
+
+            CleanupStack::PopAndDestroy(); //presIdBuf
+            CleanupStack::PushL( clientPresenceIdBuf );
+            presIdBuf = clientPresenceIdBuf;
+
+            //Remove ID from aFetchedPresenceIds array,
+            //so it won't be handled again
+            aFetchedPresenceIds.Delete( presenceIdIndex );
+            }
+
+
+        //go trough all requested attributes
+        TBool onlineStatFetched( EFalse );
+        const TInt attrTypeCount = aAttributeTypes.TypeCount();
+        for ( TInt attrTypeIx = 0; attrTypeIx < attrTypeCount; attrTypeIx++ )
+            {
+            const TUint32 attributeType = aAttributeTypes.TypeId( attrTypeIx );
+            if ( aParser.DecodeL( aPresenceBlock,
+                                  aAttributeTypes.Name( attrTypeIx ),
+                                  ETrue ) )
+                {
+                if ( attributeType == KUidPrAttrOnlineStatus )
+                    {
+                    onlineStatFetched = ETrue;
+                    }
+                //attribute type was found from presence data block
+                //Instantiate a model
+                MPEngPresenceAttrModel2* model = NULL;
+                aAttrManager.LoadAttributeLC( model,
+                                              *presIdBuf,
+                                              attributeType,
+                                              EPEngStorableModel );
+
+
+
+                //And let it to do the real parsing
+                TPtrC8 attributeData = aParser.ResultL();
+                model->Advanced()->DecodeFromXmlL( aParser, attributeData );
+
+                //add the model to results
+                aResultModels.AppendL( model );
+                CleanupStack::Pop(); //model
+                }
+
+            else
+                {
+
+
+                if ( attributeType == KUidPrAttrStatusText )
+                    {
+
+                    MPEngPresenceAttrModel2*	model = NULL;
+                    aAttrManager.LoadAttributeLC( model,
+                                                  *presIdBuf,
+                                                  KUidPrAttrStatusText,
+                                                  EPEngStorableModel );
+
+                    model->SetDataDesC16L( KNullDesC, EPEngStatusText );
+
+                    PEngAttrModelHelper::AddOrReplaceModelL( aResultModels, *model );
+                    //     aResultModels.AppendL( model );
+                    CleanupStack::Pop(); //model
+
+                    }
+                }
+            }
+        if ( !onlineStatFetched && ( aOperation == EPEngTransOpAttributeFetchToCache ) )
+            {
+            MPEngPresenceAttrModel2* model = NULL;
+            aAttrManager.LoadAttributeLC( model,
+                                          *presIdBuf,
+                                          KUidPrAttrOnlineStatus,
+                                          EPEngStorableModel );
+            //add the model to results
+            aResultModels.AppendL( model );
+            CleanupStack::Pop(); //model
+            }
+
+        CleanupStack::PopAndDestroy( presIdBuf );
+        }
+    }
+
+
+
+//  End of File
+
+