diff -r 000000000000 -r 094583676ce7 PECengine/AttributeLibrary2/SrcTransactions/CPEngFetchProcessor.cpp --- /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 +#include + + + + +// 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& 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 + +