--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/simpledatamodeladapter/src/presenceplugindata.cpp Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,1824 @@
+/*
+* Copyright (c) 2007-2010 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: IETF SIMPLE Protocol implementation for XIMP Framework
+*
+*/
+
+
+#include <e32std.h>
+#include <e32base.h>
+#include <s32strm.h>
+#include <e32def.h>
+#include <e32svr.h>
+#include <e32math.h>
+#include <utf.h>
+#include <ximpbase.h>
+#include <ximpobjectfactory.h>
+#include <ximpobjectcollection.h>
+#include <presenceobjectfactory.h>
+#include <presenceinfo.h>
+#include <personpresenceinfo.h>
+#include <presenceinfofieldcollection.h>
+#include <presenceinfofield.h>
+#include <presenceinfofieldvaluetext.h>
+#include <presenceinfofieldvalueenum.h>
+#include <ximpidentity.h>
+#include <msimpledocument.h>
+#include <msimpleelement.h>
+#include <msimplepresencelist.h>
+#include <msimplemeta.h>
+#include <simpleutils.h>
+#include <presencecachewriter2.h>
+#include <presencecachereader2.h>
+#include <presencebuddyinfo.h>
+#include <spsettings.h>
+#include <spentry.h>
+#include <spproperty.h>
+#include <spdefinitions.h>
+#include <avabilitytext.h>
+#include <cvimpstsettingsstore.h>
+
+
+#include "presenceplugindata.h"
+#include "presenceplugincommon.h"
+#include "presencepluginvirtualgroup.h"
+#include "presencepluginlanguagecodes.h"
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::CPresencePluginData
+// ---------------------------------------------------------------------------
+//
+CPresencePluginData::CPresencePluginData(
+ MPresencePluginConnectionObs& aObs,
+ TInt aServiceId ):
+ iConnObs( aObs ),
+ iServiceId( aServiceId ),
+ iPresenceCacheWriter( NULL ),
+ iPresenceCacheReader( NULL )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::~CPresencePluginData
+// ---------------------------------------------------------------------------
+//
+CPresencePluginData::~CPresencePluginData()
+ {
+ DP_SDA("CPresencePluginData::~CPresencePluginData");
+ delete iPresenceCacheWriter;
+ delete iPresenceCacheReader;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NewL
+// ---------------------------------------------------------------------------
+//
+CPresencePluginData* CPresencePluginData::NewL(
+ MPresencePluginConnectionObs& aObs, TInt aServiceId )
+ {
+ CPresencePluginData* self = CPresencePluginData::NewLC(
+ aObs,
+ aServiceId );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::ConstructL()
+ {
+ DP_SDA("CPresencePluginData::ConstructL");
+ iPresenceCacheWriter = MPresenceCacheWriter2::CreateWriterL();
+ iPresenceCacheReader = MPresenceCacheReader2::CreateReaderL();
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NewLC
+// ---------------------------------------------------------------------------
+//
+CPresencePluginData* CPresencePluginData::NewLC(
+ MPresencePluginConnectionObs& aObs, TInt aServiceId )
+ {
+ CPresencePluginData* self =
+ new( ELeave ) CPresencePluginData( aObs, aServiceId );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyToBlockedToXIMPL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyToBlockedToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MPresenceInfo& aPrInfo,
+ const TDesC& aUnicodeNoteContent )
+ {
+ DP_SDA("CPresencePluginData::NotifyToBlockedToXIMPL");
+ MPersonPresenceInfo* persInfo =
+ aPresenceFactory.NewPersonPresenceInfoLC();
+ MPresenceInfoFieldCollection& coll = persInfo->Fields();
+
+ //Set pending
+ using namespace NPresenceInfo::NFieldType;
+ using namespace NPresencePlugin::NPresenceStates;
+
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KAvailabilityEnum );
+
+ // use mapped enums to pass status
+ MPresenceInfoFieldValueEnum* enumField =
+ aPresenceFactory.NewEnumInfoFieldLC();
+
+ // HOX: BLOCKED ENUM NEEDED TO XIMP
+ enumField->SetValueL( NPresenceInfo::ENotAvailable );
+ field->SetFieldValue( enumField );
+
+ coll.AddOrReplaceFieldL( field );
+ CleanupStack::Pop( 2 ); // >> field, enumField
+
+ // Add status msg field
+ MPresenceInfoField* noteField = aPresenceFactory.NewInfoFieldLC();
+ noteField->SetFieldTypeL( KStatusMessage );
+
+ MPresenceInfoFieldValueText* textField =
+ aPresenceFactory.NewTextInfoFieldLC();
+ textField->SetTextValueL( aUnicodeNoteContent );
+
+ noteField->SetFieldValue( textField );
+
+ coll.AddOrReplaceFieldL( noteField );
+ CleanupStack::Pop( 2 ); // >> noteField, enumField
+
+ aPrInfo.SetPersonPresenceL( persInfo );
+ CleanupStack::Pop(); // >> persInfo
+ DP_SDA("CPresencePluginData::NotifyToBlockedToXIMPL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyToPendingToXIMPL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyToPendingToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MPresenceInfo& aPrInfo,
+ const TDesC& aUnicodeNoteContent )
+ {
+ DP_SDA("CPresencePluginData::NotifyToPendingToXIMP");
+ MPersonPresenceInfo* persInfo =
+ aPresenceFactory.NewPersonPresenceInfoLC();
+ MPresenceInfoFieldCollection& coll = persInfo->Fields();
+
+ //Set pending
+ using namespace NPresenceInfo::NFieldType;
+ using namespace NPresencePlugin::NPresenceStates;
+
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KAvailabilityEnum );
+
+ // use mapped enums to pass status
+ MPresenceInfoFieldValueEnum* enumField =
+ aPresenceFactory.NewEnumInfoFieldLC();
+ enumField->SetValueL( NPresenceInfo::ERemotePending );
+ field->SetFieldValue( enumField );
+
+ coll.AddOrReplaceFieldL( field );
+ CleanupStack::Pop( 2 ); // >> field, enumField
+
+ // Add status msg field
+ MPresenceInfoField* noteField = aPresenceFactory.NewInfoFieldLC();
+ noteField->SetFieldTypeL( KStatusMessage );
+
+ MPresenceInfoFieldValueText* textField =
+ aPresenceFactory.NewTextInfoFieldLC();
+ textField->SetTextValueL( aUnicodeNoteContent );
+
+ noteField->SetFieldValue( textField );
+
+ coll.AddOrReplaceFieldL( noteField );
+ CleanupStack::Pop( 2 ); // >> noteField, enumField
+
+ aPrInfo.SetPersonPresenceL( persInfo );
+ CleanupStack::Pop(); // >> persInfo
+ DP_SDA("CPresencePluginData::NotifyToPendingToXIMP end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyActiveToPrInfoL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyToActiveToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MPresenceInfo& aPrInfo,
+ const TDesC& aUnicodeNoteContent,
+ NPresenceInfo::TAvailabilityValues aAvailability )
+ {
+ DP_SDA("CPresencePluginData::NotifyToActiveToXIMPL");
+ MPersonPresenceInfo* persInfo =
+ aPresenceFactory.NewPersonPresenceInfoLC();
+ MPresenceInfoFieldCollection& coll = persInfo->Fields();
+
+ //Set pending
+ using namespace NPresenceInfo::NFieldType;
+ using namespace NPresencePlugin::NPresenceStates;
+
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KAvailabilityEnum );
+
+ // use mapped enums to pass status
+ MPresenceInfoFieldValueEnum* enumField =
+ aPresenceFactory.NewEnumInfoFieldLC();
+ enumField->SetValueL( aAvailability );
+ field->SetFieldValue( enumField );
+
+ coll.AddOrReplaceFieldL( field );
+ CleanupStack::Pop( 2 ); // >> field, enumField
+
+ // Add status msg field
+ MPresenceInfoField* noteField = aPresenceFactory.NewInfoFieldLC();
+ noteField->SetFieldTypeL( KStatusMessage );
+
+ MPresenceInfoFieldValueText* textField =
+ aPresenceFactory.NewTextInfoFieldLC();
+ textField->SetTextValueL( aUnicodeNoteContent );
+
+ noteField->SetFieldValue( textField );
+
+ coll.AddOrReplaceFieldL( noteField );
+ CleanupStack::Pop( 2 ); // >> noteField, enumField
+
+ aPrInfo.SetPersonPresenceL( persInfo );
+ CleanupStack::Pop(); // >> persInfo
+ DP_SDA("CPresencePluginData::NotifyToActiveToXIMPL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyTerminatedToPrInfoL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyTerminatedToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MPresenceInfo& aPrInfo,
+ const TDesC& aUnicodeNoteContent )
+ {
+ DP_SDA("CPresencePluginData::NotifyTerminatedToXIMPL");
+ MPersonPresenceInfo* persInfo =
+ aPresenceFactory.NewPersonPresenceInfoLC();
+ MPresenceInfoFieldCollection& coll = persInfo->Fields();
+
+ //Set pending
+ using namespace NPresenceInfo::NFieldType;
+ using namespace NPresencePlugin::NPresenceStates;
+
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KAvailabilityEnum );
+
+ // use mapped enums to pass status
+ MPresenceInfoFieldValueEnum* enumField =
+ aPresenceFactory.NewEnumInfoFieldLC();
+ enumField->SetValueL( NPresenceInfo::EOffline );
+ field->SetFieldValue( enumField );
+
+ coll.AddOrReplaceFieldL( field );
+ CleanupStack::Pop( 2 ); // >> field, enumField
+
+ // Add status msg field
+ MPresenceInfoField* noteField = aPresenceFactory.NewInfoFieldLC();
+ noteField->SetFieldTypeL( KStatusMessage );
+
+ MPresenceInfoFieldValueText* textField =
+ aPresenceFactory.NewTextInfoFieldLC();
+ textField->SetTextValueL( aUnicodeNoteContent );
+
+ noteField->SetFieldValue( textField );
+
+ coll.AddOrReplaceFieldL( noteField );
+ CleanupStack::Pop( 2 ); // >> noteField, enumField
+
+ aPrInfo.SetPersonPresenceL( persInfo );
+ CleanupStack::Pop(); // >> persInfo
+ DP_SDA("CPresencePluginData::NotifyTerminatedToXIMPL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyToPrInfoL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyToPrInfoL(
+ MXIMPObjectFactory& /*aFactory*/,
+ MPresenceObjectFactory& aPresenceFactory,
+ MSimpleDocument& aDocument,
+ MPresenceInfo& aPrInfo )
+ {
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL");
+ MPersonPresenceInfo* persInfo =
+ aPresenceFactory.NewPersonPresenceInfoLC();
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL persInfo");
+
+ if( !aDocument.EntityURI() )
+ {
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL entity URL not valid");
+ User::Leave( KErrCancel );
+ }
+
+ MPresenceInfoFieldCollection& coll = persInfo->Fields();
+
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL collection");
+ // Search own person info. Notice: Extend supported attributes later
+ TBool basicElementFound = EFalse;
+ TBool activitiesElementFound = EFalse;
+ TBool noteElemFound = EFalse;
+
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL RPointerArray");
+ RPointerArray<MSimpleElement> elems;
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL Push elems");
+ CleanupClosePushL( elems );
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL aDocument");
+ TInt err = aDocument.SimpleElementsL( elems );
+
+ DP_SDA2("CPresencePluginData::NotifyToPrInfoL err %d", err);
+
+ RPointerArray<MSimpleElement> basicElems;
+ CleanupClosePushL( basicElems );
+ MSimpleElement* basicSimpleElem(NULL);
+
+ RPointerArray<MSimpleElement> activitiesElems;
+ CleanupClosePushL( activitiesElems );
+ MSimpleElement* activitiesSimpleElem(NULL);
+ MSimpleElement* noteSimpleElem(NULL);
+
+ if ( !err )
+ {
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL, elements ok");
+ TInt count = elems.Count();
+ DP_SDA2("CPresencePluginData::NotifyToPrInfoL, element count: %d", count );
+
+ using namespace NPresencePlugin::NPresence;
+
+ MSimpleElement* elem = NULL;
+ TPtrC8 p8;
+
+ for ( TInt i = 0; i < count; i++ )
+ {
+ DP_SDA2("CPresencePluginData::NotifyToPrInfoL, handling elem[%d]", i );
+
+ elem = elems[i];
+ p8.Set( elem->LocalName());
+ if (!( p8.CompareF( KPresencePerson8 )) ||
+ !( p8.CompareF( KPresenceTuple8 )) )
+ {
+ // person element found
+ RPointerArray<MSimpleElement> elems2;
+ CleanupClosePushL( elems2 );
+ elem->SimpleElementsL( elems2 );
+ TInt count2 = elems2.Count();
+ DP_SDA2("CPresencePluginData::NotifyToPrInfoL count2 %d", count2);
+ for ( TInt j = 0; j < count2; j++ )
+ {
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL 4");
+ //
+ MSimpleElement* elem2 = elems2[j];
+
+ //FIND BASIC/ACTIVITIES ELEMENT
+ if ( !elem2->LocalName().CompareF( KPresenceStatus8 ) &&
+ !basicElementFound )
+ {
+ DP_SDA("NotifyToPrInfoL PresenceStatus");
+ //Get elem2 childs
+ elem2->SimpleElementsL( basicElems );
+ TInt count3 = basicElems.Count(); //Child count
+ for ( TInt k = 0; k < count3; k++ )
+ {
+ MSimpleElement* tempElem = basicElems[k];
+ if ( !tempElem->LocalName().CompareF(
+ KPresenceBasic8 ))
+ {
+ DP_SDA("NotifyToPrInfoL basic elem true");
+ basicSimpleElem = basicElems[k];
+ basicElementFound = ETrue;
+ }
+ else if( !tempElem->LocalName().CompareF(
+ KPresenceActivities8 ))
+ {
+ DP_SDA("NotifyToPrInfoL activities under basic");
+ activitiesSimpleElem = basicElems[k];
+ activitiesElementFound = ETrue;
+ }
+ }
+ }
+
+ //FIND ACTIVITIES ELEMENT
+ if ( basicElementFound && !activitiesElementFound &&
+ !elem2->LocalName().CompareF( KPresenceActivities8 ) )
+ {
+ DP_SDA("NotifyToPrInfoL activities found outside basic");
+ elem2->SimpleElementsL( activitiesElems );
+ TInt count4 = activitiesElems.Count();
+ for ( TInt l = 0; l < count4; l++ )
+ {
+ activitiesSimpleElem = activitiesElems[l];
+ activitiesElementFound = ETrue;
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL 6");
+ }
+ }
+ }
+
+ if ( basicElementFound && !noteSimpleElem )
+ {
+ noteSimpleElem = ResolveNoteElementL( elems2 );
+ }
+
+ DP_SDA("NotifyToPrInfoL ALL DONE");
+ CleanupStack::PopAndDestroy( &elems2 );
+
+ if ( basicElementFound && activitiesElementFound && noteElemFound )
+ {
+ DP_SDA("NotifyToPrInfoL ALL DONE break out");
+ //Just handle first status information from document
+ // In future server should support <timestamp>
+ //Also client should be can handle timestaps if there are present
+ break;
+ }
+ }
+ // Check note field
+ else if ( basicElementFound && !( p8.CompareF( KPresenceNote8 )) &&
+ !noteSimpleElem )
+ {
+ DP_SDA("NotifyToPrInfoL note field found outside tuple");
+ noteSimpleElem = elem;
+ }
+ }
+ }
+
+ if ( basicElementFound )
+ {
+ DP_SDA("NotifyToPrInfoL basic proceed to handling");
+ SingleUserStatusToXIMPL(
+ aPresenceFactory, basicSimpleElem,
+ activitiesSimpleElem, noteSimpleElem, coll );
+ }
+ CleanupStack::PopAndDestroy( &activitiesElems );
+ CleanupStack::PopAndDestroy( &basicElems );
+ CleanupStack::PopAndDestroy( &elems );
+
+ aPrInfo.SetPersonPresenceL( persInfo );
+ CleanupStack::Pop(); // >> persInfo
+
+ // TODO2: Notice: the following crashes in old PrFW version
+ /*
+ aPrInfo.AddDevicePresenceL ( NULL );
+ aPrInfo.AddServicePresenceL( NULL );
+ */
+ DP_SDA("CPresencePluginData::NotifyToPrInfoL end");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::CacheEntriesFromPrInfo
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::CacheEntriesFromPrInfo(
+ MPresenceInfo& aPrInfo,
+ MPresenceBuddyInfo2::TAvailabilityValues& aAvailability,
+ TPtr& aExtendedAvailability,
+ TPtr& aStatusMessage )
+ {
+ DP_SDA("CPresencePluginData::CacheEntriesFromPrInfoL");
+
+ DP_SDA(" -> CacheEntriesFromPrInfoL, fetch status enum field");
+ MPresenceInfoField* statusEnumInfoField = NULL;
+ MPersonPresenceInfo* presInfo = aPrInfo.PersonPresence();
+ if ( presInfo )
+ {
+ DP_SDA(" -> CacheEntriesFromPrInfoL, has person presence, get field");
+ presInfo->Fields().LookupFieldByFieldType(
+ statusEnumInfoField,
+ NPresenceInfo::NFieldType::KAvailabilityEnum );
+ DP_SDA(" -> CacheEntriesFromPrInfoL, fetch status enum field done, check item");
+ if ( statusEnumInfoField )
+ {
+ DP_SDA(" -> status enum field found");
+ const MPresenceInfoFieldValueEnum* availability =
+ TXIMPGetInterface< const MPresenceInfoFieldValueEnum >::From(
+ statusEnumInfoField->FieldValue(), MXIMPBase::EPanicIfUnknown );
+ switch( availability->Value() )
+ {
+ case NPresenceInfo::EAvailable:
+ {
+ DP_SDA(" -> status enum field => available");
+ aAvailability = MPresenceBuddyInfo2::EAvailable;
+ aExtendedAvailability.Copy( KDefaultAvailableStatus() );
+ }
+ break;
+
+ case NPresenceInfo::EBusy:
+ {
+ DP_SDA(" -> status enum field => busy");
+ aAvailability = MPresenceBuddyInfo2::EBusy;
+ aExtendedAvailability.Copy( KDndState() );
+ }
+ break;
+
+ case NPresenceInfo::EOnPhone:
+ {
+ DP_SDA(" -> status enum field => on phone");
+ aAvailability = MPresenceBuddyInfo2::EBusy;
+ aExtendedAvailability.Copy( KOnPhoneState() );
+ }
+ break;
+
+ case NPresenceInfo::EAway:
+ {
+ DP_SDA(" -> status enum field => away");
+ aAvailability = MPresenceBuddyInfo2::EBusy;
+ aExtendedAvailability.Copy( KAwayState() );
+ }
+ break;
+
+ case NPresenceInfo::EDoNotDisturb:
+ {
+ DP_SDA(" -> status enum field => dnd");
+ aAvailability = MPresenceBuddyInfo2::EBusy;
+ aExtendedAvailability.Copy( KDndState() );
+ }
+ break;
+
+ case NPresenceInfo::EOffline:
+ case NPresenceInfo::ENotAvailable:
+ default:
+ {
+ DP_SDA(" -> status enum field => offline/not available/default");
+ aAvailability = MPresenceBuddyInfo2::ENotAvailable;
+ aExtendedAvailability.Copy( KInvisibleState() );
+ }
+ break;
+ }
+ }
+ else
+ {
+ DP_SDA(" -> status enum not found => set unknown");
+ aAvailability = MPresenceBuddyInfo2::EUnknownAvailability;
+ aExtendedAvailability.Copy( KNullDesC() );
+ }
+ DP_SDA(" -> fetch status message field");
+ MPresenceInfoField* statusMsgInfoField = NULL;
+ presInfo->Fields().LookupFieldByFieldType(
+ statusMsgInfoField,
+ NPresenceInfo::NFieldType::KStatusMessage );
+ DP_SDA(" -> CacheEntriesFromPrInfoL, fetch status message field done, check item");
+ if ( statusMsgInfoField )
+ {
+ DP_SDA(" -> status msg field found");
+ const MPresenceInfoFieldValueText* statusMsg =
+ TXIMPGetInterface< const MPresenceInfoFieldValueText >::From(
+ statusMsgInfoField->FieldValue(), MXIMPBase::EPanicIfUnknown );
+ if ( statusMsg && statusMsg->TextValue().Length() )
+ {
+ DP_SDA(" -> status msg field found, copy content");
+ aStatusMessage.Copy( statusMsg->TextValue() );
+ }
+ }
+ else
+ {
+ DP_SDA(" -> status msg field not found, set empty");
+ aStatusMessage.Copy( KNullDesC() );
+ }
+ }
+
+ DP_SDA("CPresencePluginData::CacheEntriesFromPrInfoL out");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::SingleUserStatusToXIMPL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::SingleUserStatusToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MSimpleElement* aBasicElement,
+ MSimpleElement* aActivitiesElement,
+ MSimpleElement* aNoteElement,
+ MPresenceInfoFieldCollection& aCollection )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL");
+
+ using namespace NPresenceInfo::NFieldType;
+ using namespace NPresencePlugin::NPresenceStates;
+
+ //Get aBasicElem content
+ HBufC* nodeContent = aBasicElement->ContentUnicodeL();
+ CleanupStack::PushL( nodeContent );
+
+ TBuf<KBufSize100> basicContentBuf;
+ basicContentBuf.Copy( *nodeContent );
+ DP_SDA2("SingleUserStatusToXIMPL basicContent %S", &basicContentBuf);
+
+ TBuf<KBufSize100> activitiesContentBuf;
+
+ if ( !aActivitiesElement )
+ {
+ activitiesContentBuf.Copy( KPresenceUnknow );
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL activities NULL");
+ }
+ else
+ {
+ activitiesContentBuf.Copy( aActivitiesElement->LocalName() );
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL else");
+ }
+
+ if ( nodeContent )
+ {
+ using namespace NPresenceInfo::NFieldType;
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KAvailabilityEnum );
+
+ // use mapped enums to pass status
+ MPresenceInfoFieldValueEnum* enumField =
+ aPresenceFactory.NewEnumInfoFieldLC();
+
+ // Busy case
+ if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceBusy ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL open/busy");
+ enumField->SetValueL( NPresenceInfo::EBusy );
+ }
+ // On-The-Phone case
+ else if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceOnThePhone ) )
+ {
+ DP_SDA("CPresencePluginData::SingleUserStatusToXIMPL open/on-the-phone");
+ enumField->SetValueL( NPresenceInfo::EOnPhone );
+ }
+ //Away case
+ else if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceAway ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL open/away");
+ enumField->SetValueL( NPresenceInfo::EAway );
+ }
+ //Dnd case
+ else if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceDoNotDisturb ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL open/dnd");
+ enumField->SetValueL( NPresenceInfo::EDoNotDisturb );
+ }
+ // Unknown open
+ else if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceUnknow ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL open/unknown");
+ enumField->SetValueL( NPresenceInfo::EAvailable );
+ }
+ // availale open
+ else if ( !nodeContent->Des().CompareF( KPresenceOpen ) &&
+ !activitiesContentBuf.CompareF ( KPresenceAvailable ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL open/available");
+ enumField->SetValueL( NPresenceInfo::EAvailable );
+ }
+ //Unknown closed
+ else if ( !nodeContent->Des().CompareF( KPresenceClosed ) &&
+ !activitiesContentBuf.CompareF ( KPresenceUnknow ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL closed/unknown");
+ enumField->SetValueL( NPresenceInfo::EOffline );
+ }
+ //Else set status according to basic status
+ else
+ {
+ if ( !nodeContent->Des().CompareF( KPresenceOpen ) )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL else open");
+ enumField->SetValueL( NPresenceInfo::EAvailable );
+ }
+ else
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL else closed");
+ enumField->SetValueL( NPresenceInfo::ENotAvailable );
+ }
+ }
+
+ field->SetFieldValue( enumField );
+ aCollection.AddOrReplaceFieldL( field );
+
+ CleanupStack::Pop( 2 ); // >> field, enumField
+
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL check for note");
+
+ // Handle note field if found and buddy is "available".
+ if ( aNoteElement &&
+ NPresenceInfo::EOffline != enumField->Value() &&
+ NPresenceInfo::ENotAvailable != enumField->Value() )
+ {
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL note elems found");
+ // consider mapping note text to enum value if value not mapped
+ UserNoteToXIMPL( aPresenceFactory, aNoteElement, aCollection );
+ }
+ }
+ CleanupStack::PopAndDestroy( nodeContent );
+ DP_SDA(" CPresencePluginData::SingleUserStatusToXIMPL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::UserNoteToXIMPL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::UserNoteToXIMPL(
+ MPresenceObjectFactory& aPresenceFactory,
+ MSimpleElement* aElement,
+ MPresenceInfoFieldCollection& aCollection )
+ {
+ DP_SDA(" CPresencePluginData::UserNoteToXIMPL IN");
+ HBufC* nodeContent = aElement->ContentUnicodeL();
+ CleanupStack::PushL( nodeContent );
+ if ( nodeContent )
+ {
+ DP_SDA(" CPresencePluginData::UserNoteToXIMPL - content found");
+ // Save note, convert from unicode
+ // notice: consider xml::lang-attribute
+ // note <-> KStatusMessage
+ // notice: no need to consider namespaces in XML?
+ using namespace NPresenceInfo::NFieldType;
+
+ DP_SDA(" CPresencePluginData::UserNoteToXIMPL - create fields");
+ MPresenceInfoField* field = aPresenceFactory.NewInfoFieldLC();
+ field->SetFieldTypeL( KStatusMessage );
+ MPresenceInfoFieldValueText* text =
+ aPresenceFactory.NewTextInfoFieldLC();
+ text->SetTextValueL( nodeContent->Des() );
+ field->SetFieldValue( text );
+ CleanupStack::Pop(); // >> text
+ aCollection.AddOrReplaceFieldL( field );
+ CleanupStack::Pop(); // >> field
+ DP_SDA(" -> fields added to collection");
+ }
+ CleanupStack::PopAndDestroy( nodeContent );
+ DP_SDA(" CPresencePluginData::UserNoteToXIMPL OUT");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::NotifyListToPrInfoL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::NotifyListToPrInfoL(
+ MXIMPObjectFactory& aFactory,
+ MPresenceObjectFactory& aPresenceFactory,
+ MSimplePresenceList& aList,
+ RPointerArray<MPresenceInfo>& aEntities,
+ RPointerArray<MXIMPIdentity>& aActives,
+ RPointerArray<MXIMPIdentity>& aTerminated )
+ {
+ DP_SDA(" CPresencePluginData::NotifyListToPrInfoL");
+ // Split array into individual prInfos
+
+ aEntities.Reset();
+ RPointerArray<MSimpleDocument> docs;
+ CleanupClosePushL( docs );
+ // get documents, ownership is not transferred.
+ aList.GetDocuments( docs );
+
+ TInt count = docs.Count();
+
+ // active presentities
+ for ( TInt i = 0; i < count; i++ )
+ {
+ MPresenceInfo* info =
+ aPresenceFactory.NewPresenceInfoLC();//<< info
+ aEntities.Append( info );
+ // aEntities may contain entries even this method leaves
+ CleanupStack::Pop();// >> info
+
+ NotifyToPrInfoL( aFactory, aPresenceFactory, *docs[i], *info );
+ // Add SIp identity to active users list
+ MXIMPIdentity* active = aFactory.NewIdentityLC();// << active
+ aActives.Append( active );
+ CleanupStack::Pop();// >> active
+
+ // Convert SIP entity URI from UTF to Unicode.
+ const TDesC8* pUri8 = (docs[i])->EntityURI();
+ HBufC16* uri16 = NULL;
+ uri16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *pUri8 );
+ CleanupStack::PushL( uri16 ); // << uri16
+ active->SetIdentityL( uri16->Des() );
+ CleanupStack::PopAndDestroy( uri16 );// >> uri16
+ }
+
+ using namespace NPresencePlugin::NPresence;
+
+ // Search "terminated" presentities
+ MSimpleMeta* meta = aList.MetaData();
+ // ownership in not transferred
+ if ( meta && !meta->LocalName().CompareF( KPresenceList8 ))
+ {
+ // list element found
+ RPointerArray<MSimpleElement> elems2;
+ CleanupClosePushL( elems2 );
+ meta->SimpleElementsL( elems2);
+ TInt count2 = elems2.Count();
+
+ for ( TInt i = 0; i < count2; i++ )
+ {
+ MSimpleElement* elem2 = elems2[i];
+ if ( !elem2->LocalName().CompareF( KPresenceResource8 ))
+ {
+ // resource element
+ RPointerArray<MSimpleElement> elems3;
+ CleanupClosePushL( elems3 );
+ meta->SimpleElementsL( elems3 );
+ TInt count3 = elems3.Count();
+
+ for ( TInt j=0; j < count3; j++ )
+ {
+ MSimpleElement* elem3 = elems3[i];
+
+ if ( !elem3->LocalName().CompareF( KPresenceInstance8 ))
+ {
+ // instance element
+ const TDesC8* stateVal =
+ elem3->AttrValue( KPresenceState8 );
+ if ( stateVal && stateVal->
+ CompareF( KPresenceTerminated8 ))
+ {
+ // get next entity if this is not state="terminated"
+ break;
+ }
+ // Save resource element URI into list of
+ // "terminated" users.
+ const TDesC8* uri8 = elem2->AttrValue( KPresenceUri8 );
+ MXIMPIdentity* terminated =
+ aFactory.NewIdentityLC();// << terminated
+ aTerminated.Append( terminated );
+ CleanupStack::Pop(); // >> terminated
+
+ // Convert SIP entity URI from UTF to Unicode.
+ HBufC16* uri16 = NULL;
+ uri16 =
+ CnvUtfConverter::ConvertToUnicodeFromUtf8L( *uri8 );
+ CleanupStack::PushL( uri16 ); // << uri16
+ terminated->SetIdentityL( uri16->Des() );
+ CleanupStack::PopAndDestroy( uri16 ); // >> uri16
+ }
+ }
+ CleanupStack::PopAndDestroy( &elems3 );
+ } // resource element
+ }// for (i); list element subelement
+ CleanupStack::PopAndDestroy( &elems2 );
+ }
+
+ CleanupStack::PopAndDestroy( &docs );
+ DP_SDA(" CPresencePluginData::NotifyListToPrInfoL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::AddPrPersToSimpleDocumentL
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::AddPrPersToSimpleDocumentL(
+ const MPersonPresenceInfo* aInfo,
+ MSimpleDocument& aDocument,
+ const TDesC8& aSipId, TInt aTupleId )
+ {
+ DP_SDA("CPresencePluginData::AddPrPersToSimpleDocumentL start");
+ iNumBuf = aTupleId;
+ // notice: later: generate random id.
+
+ using namespace NPresencePlugin::NPresence;
+ using namespace NPresenceInfo::NFieldType;
+
+ const MPresenceInfoFieldCollection& coll = aInfo->Fields();
+
+ const MPresenceInfoField* statusEmumField = NULL;
+ const MPresenceInfoField* messageField = NULL;
+
+ TInt myCount = coll.FieldCount();
+ for ( TInt i = 0; i < myCount; i++ )
+ {
+ DP_SDA("CPresencePluginData::AddPrPersToSimpleDocumentL 1");
+
+ const MPresenceInfoField& field = coll.FieldAt( i );
+ const TDesC8& fieldType = field.FieldType();
+ TBuf<KBufSize100> printBuf;
+ printBuf.Copy( fieldType );
+
+ if ( !fieldType.Compare( KAvatar ) )
+ {
+ // Do nothing in sawfis, maybe later?
+ }
+ else if ( !fieldType.Compare( KAvailabilityEnum ) )
+ {
+ DP_SDA("AddPrPersToSimpleDocumentL Avaibility");
+ statusEmumField = &field;
+ DP_SDA("AddPrPersToSimpleDocumentL Avaibility done");
+ }
+ else if ( !fieldType.Compare( KStatusMessage ) )
+ {
+ DP_SDA("AddPrPersToSimpleDocumentL statusmessage");
+ messageField = &field;
+ }
+ }
+ if ( statusEmumField )
+ {
+ DoCreateDocumentL( aDocument, aSipId,
+ statusEmumField, messageField );
+ }
+
+
+ DP_SDA("CPresencePluginData::AddPrPersToSimpleDocumentL end");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::CreatePresenceUri8LC
+// ---------------------------------------------------------------------------
+//
+HBufC8* CPresencePluginData::CreatePresenceUri8LC(
+ const TDesC8& aPresentityUri )
+ {
+ DP_SDA("CPresencePluginData::CreatePresenceUri8LC ");
+ const TInt KMyLenSipPrefix = 4;
+ const TInt KMyLenSipsPrefix = 5;
+ _LIT8( KMySip8, "sip:" );
+ _LIT8( KMySips8, "sips:" );
+ TInt uriLen = aPresentityUri.Length();
+ DP_SDA2( "CPresencePluginData::CreatePresenceUri8LC - param length: %d ", uriLen );
+
+ //For debugging purposes
+ //TBuf<256> tmpPresentityUri;
+ //tmpPresentityUri.Copy( aPresentityUri );
+ //DP_SDA2( "CPresencePluginData::CreatePresenceUri8LC - URI: %S ", &tmpPresentityUri );
+
+ HBufC8* buf = HBufC8::NewLC( uriLen );
+ TPtr8 pBuf( buf->Des() );
+
+ //SIP uri check
+ if ( !aPresentityUri.Left( KMyLenSipPrefix ).CompareF( KMySip8 ) )
+ {
+ DP_SDA("CPresencePluginData::CreatePresenceUri8LC (sip:) prefix in SIP URI ");
+ pBuf.Append( aPresentityUri );
+ }
+ else if ( !aPresentityUri.Left( KMyLenSipsPrefix ).CompareF( KMySips8 ) )
+ {
+ DP_SDA( "CPresencePluginData::CreatePresenceUri8LC (sips:) prefix in SIP URI " );
+ pBuf.Append( aPresentityUri );
+ }
+ else // No prefix, strange ...
+ {
+ DP_SDA( "CPresencePluginData::CreatePresenceUri8LC NO prefix in SIP URI, adding... " );
+ // Maybe should check which prefix to use,
+ // but assume that no secure is used if prefix missing
+ TInt len = aPresentityUri.Length() + KMyLenSipPrefix;
+ buf = buf->ReAllocL( len );
+ //update pointer after realloc
+ CleanupStack::Pop( 1 );
+ CleanupStack::PushL( buf );
+ // Since realloc may have changed the location in memory
+ // we must also reset ptr
+ pBuf.Set( buf->Des() );
+ pBuf.Append( KMySip8 );
+ pBuf.Append( aPresentityUri );
+ }
+ return buf;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::RemovePrefixLC
+// ---------------------------------------------------------------------------
+//
+HBufC16* CPresencePluginData::RemovePrefixLC(
+ const TDesC& aPresentityUri )
+ {
+ DP_SDA2("CPresencePluginData::RemovePrefixLC, uri: %S", &aPresentityUri );
+
+ HBufC* withouPrefix = HBufC::NewLC( KBufSize255 );
+ TPtr withouPrefixPtr( withouPrefix->Des() );
+
+ TInt prefixLocation = aPresentityUri.Locate( ':' );
+ DP_SDA2("CPresencePluginData::RemovePrefixLC, prefix pos: %d", prefixLocation );
+ if ( KErrNotFound != prefixLocation )
+ {
+ DP_SDA("CPresencePluginData::RemovePrefixLC - has prefix");
+ withouPrefixPtr.Copy( aPresentityUri.Mid( prefixLocation+1 ) );
+ DP_SDA("CPresencePluginData::RemovePrefixLC - copy ok");
+ }
+ else
+ {
+ DP_SDA("CPresencePluginData::RemovePrefixLC - has no prefix");
+ withouPrefixPtr.Copy( aPresentityUri );
+ }
+
+ //DP_SDA2("CPresencePluginData::RemovePrefixLC - returns %S", *withouPrefix );
+ return withouPrefix;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DoCreateDocumentL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::DoCreateDocumentL(
+ MSimpleDocument& aDocument,
+ const TDesC8& aSipId,
+ const MPresenceInfoField* aStatusField,
+ const MPresenceInfoField* aMessageField )
+ {
+ DP_SDA("CPresencePluginData::DoCreateDocumentL ");
+ const TInt KNumBuf = 20;
+ const TInt KTupleBuf = 10;
+
+ using namespace NPresencePlugin::NPresence;
+ using namespace NPresencePlugin::NPresenceStates;
+ using namespace NPresenceInfo::NFieldType;
+
+ TBuf<KNumBuf> numBuf;
+ TBuf<KTupleBuf> tupleBuf;
+
+ tupleBuf.Copy( KIndent );
+ numBuf.Num( iNumBuf );
+ tupleBuf.Append( numBuf );
+ DP_SDA2("CPresencePluginData::DoCreateDocumentL id %d", iNumBuf);
+ DP_SDA("CPresencePluginData::DoCreateDocumentL 2");
+
+ //Add tuple id to document
+ MSimpleElement* tuple = aDocument.AddSimpleElementL( KPresenceTuple8 );
+ CleanupClosePushL( *tuple );
+ tuple->AddAttrL( KPresenceId8, tupleBuf);
+
+ //Presence status field
+ MSimpleElement* status = tuple->AddSimpleElementL( KPresenceStatus8 );
+ CleanupClosePushL( *status );
+
+ //basic field
+ MSimpleElement* basic = status->AddSimpleElementL( KPresenceBasic8 );
+ CleanupClosePushL( *basic );
+
+ basic->SetContentUnicodeL( DoCheckBasicStatusValueL( *aStatusField ) );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Basic ok, check msg");
+
+ if ( aMessageField )
+ {
+ DP_SDA("CPresencePluginData::DoCreateDocumentL message field");
+ //Creating note
+ MSimpleElement* note =
+ aDocument.AddSimpleElementL( KPresenceNote8 );
+ CleanupClosePushL( *note );
+
+ // Get status msg field from info field
+ const MPresenceInfoFieldValueText* textField =
+ TXIMPGetInterface<
+ const MPresenceInfoFieldValueText >::From(
+ aMessageField->FieldValue(),
+ MXIMPBase::EPanicIfUnknown );
+ note->SetContentUnicodeL( textField->TextValue() );
+ CleanupStack::PopAndDestroy( note );
+ }
+
+ /* Basic model example
+ <tuple id="c8dqui">
+ <status>
+ <basic>open</basic>
+ </status>
+ <ts:basic>closed</ts:basic>
+ </ts:timed-status>
+ <contact>sip:someone@example.com</contact>
+ </tuple>
+ <note>sleeping</note>
+ </presence>
+ */
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Rich presence person");
+ //Creatin person presence field
+ MSimpleElement* pers =
+ aDocument.AddSimpleElementL( KSimpleNsPDM, KPresencePerson8 );
+ CleanupClosePushL( *pers );
+ TBuf<KBufSize10> buf;
+ TBuf<KBufSize20> personId;
+ personId.Copy( KPersonId );
+ buf.Num( iNumBuf );
+ personId.Append( buf );
+ pers->AddAttrL( KPresenceId8, personId );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Rich presence person ok");
+
+ HBufC8* urlBuf = CreatePresenceUri8LC( aSipId );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Push urlBuf");
+
+ aDocument.SetEntityURIL( urlBuf->Des() );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL 2");
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentLC Rich presence activities");
+ MSimpleElement* activ = pers->AddSimpleElementL(
+ KSimpleNsRPID, KPresenceActivities8 );
+ CleanupClosePushL( *activ );
+
+ //unknown used if person presence is just open or closed
+ MSimpleElement* unknown = activ->AddSimpleElementL(
+ KSimpleNsRPID, DoCheckActivitiesValueL( *aStatusField ) );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL, unknown/status element created");
+ CleanupClosePushL( *unknown );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy unknown");
+ CleanupStack::PopAndDestroy( unknown );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy activ");
+ CleanupStack::PopAndDestroy( activ );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy urlBuf");
+ CleanupStack::PopAndDestroy( urlBuf );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy pers");
+ CleanupStack::PopAndDestroy( pers );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Rich presence activities ok");
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy basic");
+ CleanupStack::PopAndDestroy( basic );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy status");
+ CleanupStack::PopAndDestroy( status );
+
+ DP_SDA("CPresencePluginData::DoCreateDocumentL Destroy tuple");
+ CleanupStack::PopAndDestroy( tuple );
+ DP_SDA("CPresencePluginData::DoCreateDocumentL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DoCheckBasicStatusValueL()
+// ---------------------------------------------------------------------------
+//
+TPtrC CPresencePluginData::DoCheckBasicStatusValueL(
+ const MPresenceInfoField& aField )
+ {
+ using namespace NPresencePlugin::NPresence;
+ using namespace NPresencePlugin::NPresenceStates;
+ using namespace NPresenceInfo::NFieldType;
+
+ TPtrC basicStatus( KPresenceOpen ); //default status open
+ //First check what is person status value
+ const MXIMPBase& storage = aField.FieldValue();
+ const MPresenceInfoFieldValueEnum* enumObject =
+ TXIMPGetInterface< const MPresenceInfoFieldValueEnum >::
+ From( storage,MXIMPBase::EReturnNullIfUnknown );
+
+ __ASSERT_ALWAYS( NULL != enumObject, User::Leave( KErrArgument ) );
+
+ DP_SDA2(" DoCheckBasicStatusValueL - enumValue: %d", enumObject->Value() );
+ switch ( enumObject->Value() )
+ {
+ case NPresenceInfo::EAvailable:
+ {
+ DP_SDA("DoCheckBasicStatusValueL stopPublish false status open");
+ iConnObs.SetStopPublishState( EFalse );
+ basicStatus.Set( KPresenceOpen );
+ }
+ break;
+
+ case NPresenceInfo::EOffline:
+ case NPresenceInfo::EHidden:
+ case NPresenceInfo::ENotAvailable:
+ {
+ //If state is closed we can stop publish
+ //if client is going to offline
+ DP_SDA("DoCheckBasicStatusValueL stopPublish true status Closed");
+ iConnObs.SetStopPublishState( ETrue );
+ basicStatus.Set( KPresenceClosed );
+ }
+ break;
+
+ default:
+ {
+ DP_SDA("DoCheckBasicStatusValueL stopPublish false else open");
+ iConnObs.SetStopPublishState( EFalse );
+ basicStatus.Set( KPresenceOpen );
+ }
+ break;
+ }
+ return basicStatus;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DoCheckActivitiesValueL()
+// ---------------------------------------------------------------------------
+//
+TPtrC8 CPresencePluginData::DoCheckActivitiesValueL(
+ const MPresenceInfoField& aField )
+ {
+ using namespace NPresencePlugin::NPresence;
+ using namespace NPresencePlugin::NPresenceStates;
+ using namespace NPresenceInfo::NFieldType;
+
+ TPtrC8 activities( KPresenceUnknow8 ); //default activities unknown
+
+ const MXIMPBase& storage = aField.FieldValue();
+ const MPresenceInfoFieldValueEnum* enumObject =
+ TXIMPGetInterface< const MPresenceInfoFieldValueEnum >::
+ From( storage,MXIMPBase::EReturnNullIfUnknown );
+
+ __ASSERT_ALWAYS( NULL != enumObject, User::Leave( KErrArgument ) );
+
+ DP_SDA2(" DoCheckActivitiesValueL - enumValue: %d", enumObject->Value() );
+ switch ( enumObject->Value() )
+ {
+ case NPresenceInfo::EAvailable:
+ {
+ DP_SDA("DoCheckActivitiesValueL - available, set publish");
+ iConnObs.SetStopPublishState( EFalse );
+ DP_SDA("DoCheckActivitiesValueL - available, set value");
+ activities.Set( KPresenceUnknow8 );
+ DP_SDA("DoCheckActivitiesValueL - available, ok");
+ }
+ break;
+
+ case NPresenceInfo::EOffline:
+ case NPresenceInfo::ENotAvailable:
+ {
+ DP_SDA("DoCheckActivitiesValueL - offline/not available");
+ iConnObs.SetStopPublishState( ETrue );
+ activities.Set( KPresenceUnknow8 );
+ }
+ break;
+
+ case NPresenceInfo::EBusy:
+ {
+ DP_SDA("DoCheckActivitiesValueL - busy");
+ iConnObs.SetStopPublishState( EFalse );
+ activities.Set( KPresenceBusy8 );
+ }
+ break;
+
+ case NPresenceInfo::EExtAway:
+ case NPresenceInfo::EAway:
+ {
+ DP_SDA("DoCheckActivitiesValueL - away");
+ iConnObs.SetStopPublishState( EFalse );
+ activities.Set( KPresenceAway8 );
+ }
+ break;
+
+ case NPresenceInfo::EOnPhone:
+ {
+ DP_SDA("DoCheckActivitiesValueL - on phone");
+ iConnObs.SetStopPublishState( EFalse );
+ activities.Set( KPresenceOnThePhone8 );
+ }
+ break;
+
+
+ case NPresenceInfo::EDoNotDisturb:
+ {
+ DP_SDA("DoCheckActivitiesValueL - dnd");
+ iConnObs.SetStopPublishState( EFalse );
+ activities.Set( KPresenceDoNotDisturb8 );
+ }
+ break;
+
+ default:
+ {
+ DP_SDA("DoCheckActivitiesValueL default => unknown");
+ iConnObs.SetStopPublishState( EFalse );
+ activities.Set( KPresenceUnknow8 );
+ }
+ break;
+ }
+ DP_SDA("DoCheckActivitiesValueL - done and return");
+ return activities;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DoCheckNoteValueL()
+// ---------------------------------------------------------------------------
+//
+TPtrC CPresencePluginData::DoCheckNoteValueL(
+ const MPresenceInfoField& aField )
+ {
+ using namespace NPresencePlugin::NPresence;
+ using namespace NPresencePlugin::NPresenceStates;
+ using namespace NPresenceInfo::NFieldType;
+
+ TPtrC note( KPresenceUnknow ); //default activities unknown
+ //First check what is person status value
+ const MXIMPBase& storage = aField.FieldValue();
+ const MPresenceInfoFieldValueText* text =
+ TXIMPGetInterface< const MPresenceInfoFieldValueText >::
+ From( storage,MXIMPBase::EReturnNullIfUnknown );
+
+ __ASSERT_ALWAYS( NULL != text, User::Leave( KErrArgument ) );
+
+ TBuf<KBufSize200> buffer;
+ buffer.Copy( text->TextValue() );
+
+ //Check if status is closed
+ if( !buffer.CompareF( KPresenceClosed ) )
+ {
+ //If state is closed we can stop publish
+ //if client is going to offline
+ DP_SDA("DoCheckNoteValueL stopPublish true closed");
+ iConnObs.SetStopPublishState( ETrue );
+ note.Set( KPresenceOffline );
+ }
+ else if( !buffer.CompareF( KPresenceOpen ) )
+ {
+ DP_SDA("DoCheckNoteValueL stopPublish false open");
+ iConnObs.SetStopPublishState( EFalse );
+ note.Set( KPresenceAvailable );
+ }
+ else if( !buffer.CompareF( KPresenceBusy ) )
+ {
+ DP_SDA("DoCheckNoteValueL activities BUSY");
+ iConnObs.SetStopPublishState( EFalse );
+ note.Set( KPresenceBusy );
+ }
+ else if( !buffer.CompareF( KPresenceOnThePhone ) )
+ {
+ DP_SDA("DoCheckNoteValueL activities OnThePhone");
+ iConnObs.SetStopPublishState( EFalse );
+ note.Set( KPresenceOnThePhone );
+ }
+ else if( !buffer.CompareF( KPresenceAway ) )
+ {
+ DP_SDA("DoCheckNoteValueL activities OnThePhone");
+ iConnObs.SetStopPublishState( EFalse );
+ note.Set( KPresenceAway );
+ }
+ else
+ {
+ DP_SDA("DoCheckNoteValueL stopPublish false");
+ iConnObs.SetStopPublishState( EFalse );
+ note.Set( KPresenceUnknow );
+ }
+ return note;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::GenerateTupleId()
+// ---------------------------------------------------------------------------
+//
+TInt CPresencePluginData::GenerateTupleId()
+ {
+ // Generate unique session tuple id
+ DP_SDA("CPresencePluginData::GenerateTupleId start");
+ const TInt KMaxRand = KMaxNumber;
+ TInt64 seed;
+ TTime time;
+ time.HomeTime();
+ seed = time.Int64();
+ TInt random = Math::Rand( seed ) % KMaxRand;
+ DP_SDA("CPresencePluginData::GenerateTupleId 1");
+ return random;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ServiceId()
+// ---------------------------------------------------------------------------
+//
+TInt CPresencePluginData::ServiceId()
+ {
+ return iServiceId;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ServiceNameLC()
+// ---------------------------------------------------------------------------
+//
+HBufC* CPresencePluginData::ServiceNameLC( TInt aServiceId ) const
+ {
+ CSPSettings* spSettings = CSPSettings::NewLC();
+ CSPEntry* entry = CSPEntry::NewLC();
+ HBufC* serviceName = NULL;
+
+ User::LeaveIfError( spSettings->FindEntryL( aServiceId, *entry ) );
+
+ serviceName = entry->GetServiceName().AllocL();
+
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( spSettings );
+ CleanupStack::PushL( serviceName );
+ return serviceName;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ResolveCacheXspIdentifierL()
+// ---------------------------------------------------------------------------
+//
+HBufC* CPresencePluginData::ResolveCacheXspIdentifierL(
+ const TDesC& aIdentity ) const
+ {
+ DP_SDA( "CPresencePluginData::ResolveCacheXspIdentifierL" );
+
+ CSPSettings* spSettings = CSPSettings::NewLC();
+ CSPEntry* entry = CSPEntry::NewLC();
+
+ User::LeaveIfError( spSettings->FindEntryL( iServiceId, *entry ) );
+
+ TInt cacheUriLength = ( entry->GetServiceName().Length() +
+ aIdentity.Length() + 1 );
+
+ HBufC* cacheUri = HBufC::NewL( cacheUriLength );
+ TPtr cacheUriPtr( cacheUri->Des() );
+
+ cacheUriPtr.Append( entry->GetServiceName() );
+ cacheUriPtr.Append( ':' );
+ cacheUriPtr.Append( aIdentity );
+
+ CleanupStack::PopAndDestroy( entry );
+ CleanupStack::PopAndDestroy( spSettings );
+
+ DP_SDA2( "CPresencePluginData::ResolveCacheXspIdentifierL returns: %S", cacheUri );
+ return cacheUri;
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::WriteBlockItemsToCacheL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::WriteStatusToCacheL(
+ const TDesC& aPresentityId,
+ MPresenceBuddyInfo2::TAvailabilityValues aAvailability,
+ const TDesC& aAvailabilityText,
+ const TDesC& aStatusMessage )
+ {
+ DP_SDA( "CPresencePluginData::WriteStatusToCacheL start" );
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, aStatus: %d",
+ aAvailability );
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, availabilityText: %S",
+ &aAvailabilityText );
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, statusMessage: %S",
+ &aStatusMessage );
+
+ TBool updateCache( ETrue );
+
+ HBufC* cacheUri = ResolveCacheXspIdentifierL( aPresentityId );
+ CleanupStack::PushL( cacheUri );
+
+ DP_SDA(" -> WriteStatusToCacheL - read previous values from cache");
+
+ // Read previous values from cache
+ MPresenceBuddyInfo2* previousPresInfo =
+ iPresenceCacheReader->PresenceInfoLC( *cacheUri );
+
+ if ( previousPresInfo )
+ {
+ DP_SDA(" -> WriteStatusToCacheL - get availability value");
+
+ MPresenceBuddyInfo2::TAvailabilityValues availability =
+ previousPresInfo->Availability();
+
+ DP_SDA(" -> WriteStatusToCacheL - get availability text");
+
+ TPtrC availabilityText = previousPresInfo->AvailabilityText();
+
+ DP_SDA(" -> WriteStatusToCacheL - get status message");
+
+ TPtrC statusMessage = previousPresInfo->StatusMessage();
+ CleanupStack::PopAndDestroy(); //previousPresInfo
+
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, OLD STATUS: %d",
+ availability );
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, OLD AVAILABILITY TEXT: %S",
+ &availabilityText );
+ DP_SDA2( "CPresencePluginData::WriteStatusToCacheL, OLD STATUS MESSAGE: %S",
+ &statusMessage );
+
+ if ( ( aAvailability == availability ) &&
+ ( aAvailabilityText.Compare( availabilityText ) == 0 ) &&
+ ( aStatusMessage.Compare( statusMessage ) == 0 ))
+ {
+ DP_SDA(" -> WriteStatusToCacheL - no need to update cache");
+ updateCache = EFalse;
+ }
+ }
+
+ if ( updateCache )
+ {
+ MPresenceBuddyInfo2* newPresInfo = MPresenceBuddyInfo2::NewLC();
+ newPresInfo->SetIdentityL( *cacheUri );
+
+ DP_SDA(" -> WriteStatusToCacheL - update cache");
+
+ TBuf<KBufSize20> buf;
+ TBool handled = EFalse;
+
+ buf.Copy( KBlockedExtensionValue );
+
+ if( aAvailabilityText.Compare( buf ) == 0 )
+ {
+ DP_SDA( " -> WriteStatusToCacheL - set Blocked" );
+ newPresInfo->SetAnyFieldL( KExtensionKey, KBlockedExtensionValue );
+ handled = ETrue;
+ }
+
+ buf.Copy( KPendingRequestExtensionValue );
+
+ if ( aAvailabilityText.Compare( buf ) == 0 )
+ {
+ DP_SDA( " -> WriteStatusToCacheL - set Pending request" );
+ newPresInfo->SetAnyFieldL( KExtensionKey, KPendingRequestExtensionValue );
+ handled = ETrue;
+ }
+
+ if ( !handled )
+ {
+ DP_SDA2( " -> WriteStatusToCacheL - set availability text: %S", &aAvailabilityText );
+ newPresInfo->SetAvailabilityL( aAvailability, aAvailabilityText );
+ }
+
+ if ( aStatusMessage.Length() )
+ {
+ DP_SDA2( " -> WriteStatusToCacheL - set status message: %S", &aStatusMessage );
+ newPresInfo->SetStatusMessageL( aStatusMessage );
+ }
+
+ DP_SDA( " -> WriteStatusToCacheL - write presence to cache" );
+ TInt cacheError = iPresenceCacheWriter->WritePresenceL( newPresInfo );
+ DP_SDA2( "CPresencePluginEntityWatcher::WriteStatusToCacheL error: %d",
+ cacheError );
+
+ DP_SDA( " -> destroy buddy info" );
+ CleanupStack::PopAndDestroy(); // newPresInfo
+ }
+
+ DP_SDA(" -> destroy uri");
+ CleanupStack::PopAndDestroy( cacheUri );
+
+ DP_SDA("CPresencePluginData::WriteStatusToCacheL end");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::RemoveCacheL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::RemoveCacheL()
+ {
+ DP_SDA("CPresencePluginData::RemoveCacheL");
+
+ // Resolve service name (cache xsp identifier)
+ CSPSettings* spSettings = CSPSettings::NewL();
+ CleanupStack::PushL( spSettings );
+
+ CSPEntry* entry = CSPEntry::NewLC();
+ DP_SDA2(" -> RemoveCacheL look for service: %d", ServiceId() );
+ spSettings->FindEntryL( ServiceId(), *entry );
+
+ DP_SDA(" -> RemoveCacheL cache xsp identifier found");
+ TInt cacheUriLength = entry->GetServiceName().Length();
+ DP_SDA2(" -> cache uri length: %d", cacheUriLength );
+
+ HBufC* cacheUri = HBufC::NewLC( cacheUriLength );
+ TPtr cacheUriPtr( cacheUri->Des() );
+
+ DP_SDA(" -> RemoveCacheL - form cache entry");
+ cacheUriPtr.Append( entry->GetServiceName() );
+
+ DP_SDA(" -> RemoveCacheL - delete cache entries");
+ TInt error = iPresenceCacheWriter->DeleteService( cacheUriPtr );
+ DP_SDA2(" -> RemoveCacheL - delete error: %d", error );
+ CleanupStack::PopAndDestroy( cacheUri );
+
+ DP_SDA(" -> destroy sp entry");
+ CleanupStack::PopAndDestroy( entry );
+ DP_SDA(" -> destroy sp");
+ CleanupStack::PopAndDestroy( spSettings );
+ DP_SDA("CPresencePluginData::RemoveCacheL out");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DeletePresenceL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::DeletePresenceL( const TDesC& aIdentity )
+ {
+ DP_SDA("CPresencePluginData::DeletePresenceL");
+
+ // Resolve service name (cache xsp identifier)
+ CSPSettings* spSettings = CSPSettings::NewL();
+ CleanupStack::PushL( spSettings );
+ CSPEntry* entry = CSPEntry::NewLC();
+ DP_SDA2(" -> DeletePresenceL look for service: %d", ServiceId() );
+ spSettings->FindEntryL( ServiceId(), *entry );
+
+ DP_SDA(" -> DeletePresenceL cache xsp identifier found");
+ TInt cacheUriLength = ( entry->GetServiceName().Length() +
+ aIdentity.Length() + 1 );
+ DP_SDA2(" -> cache uri length: %d", cacheUriLength );
+
+ HBufC* cacheUri = HBufC::NewLC( cacheUriLength );
+ TPtr cacheUriPtr( cacheUri->Des() );
+
+ DP_SDA(" -> DeletePresenceL - form cache entry");
+ cacheUriPtr.Append( entry->GetServiceName() );
+ cacheUriPtr.Append( ':' );
+ cacheUriPtr.Append( aIdentity );
+
+ iPresenceCacheWriter->DeletePresenceL( cacheUriPtr );
+
+ CleanupStack::PopAndDestroy( cacheUri );
+ CleanupStack::PopAndDestroy( entry );
+ DP_SDA(" -> destroy sp");
+ CleanupStack::PopAndDestroy( spSettings );
+ DP_SDA("CPresencePluginData::DeletePresenceL out");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::StorePresenceOwnPresenceL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::StorePresenceOwnPresenceL(
+ const TUint aServiceId,
+ NPresenceInfo::TAvailabilityValues aAvailability,
+ const TDesC& aStatusMessage )
+ {
+ DP_SDA("CPresencePluginData::StorePresenceOwnPresenceL IN");
+ DP_SDA2(" -> aServiceId: %d", aServiceId );
+
+ DP_SDA2(" -> SAVE AVAILABILITY VALUE: %d", aAvailability );
+ DP_SDA2(" -> SAVE STATUS MESSAGE: %S", &aStatusMessage );
+
+ MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC();
+
+ DP_SDA("CPresencePluginData::StorePresenceOwnPresenceL 1");
+
+ // Store availability value to uiservicetabsettings
+ TInt availabilityInt = ( ( TInt ) aAvailability );
+ User::LeaveIfError( settings->SetL(
+ aServiceId, EServicePresenceAvailablilityValue, availabilityInt ) );
+
+ DP_SDA("CPresencePluginData::StorePresenceOwnPresenceL 2");
+
+ // Store custom status message to uiservicetabsettings
+ User::LeaveIfError( settings->SetL(
+ aServiceId, EServiceCustomStatusMessage, aStatusMessage ) );
+
+ CleanupStack::PopAndDestroy(); //settings
+
+ DP_SDA("CPresencePluginData::StorePresenceOwnPresenceL OUT");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ReadDocumentIdL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::ReadDocumentIdL(
+ const TInt aServiceId,
+ TDes8& aDocumentId )
+ {
+ DP_SDA("CPresencePluginData::ReadDocumentIdL IN");
+
+ DP_SDA2(" -> aServiceId: %d", aServiceId );
+
+ MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC();
+
+ RBuf8 documentId;
+ CleanupClosePushL( documentId );
+ documentId.CreateL( KBufSize255 );
+
+ TInt error = settings->GetL(
+ aServiceId, EServicePresenceSessionIdentifier, documentId );
+
+ DP_SDA2(" -> ERROR: %d", error );
+ DP_SDA2(" -> DOCUMENT ID LENGTH: %d", documentId.Length() );
+
+ if ( !error && documentId.Length() )
+ {
+ aDocumentId.Copy( documentId );
+
+ TBuf<KBufSize255> printDocumentId;
+ printDocumentId.Copy( aDocumentId );
+ DP_SDA("CPresencePluginData::ReadDocumentIdL - 1");
+ DP_SDA2(" -> READ DOCUMENT ID: %S", &printDocumentId );
+ }
+ else if ( KErrNotFound == error || !documentId.Length() )
+ {
+ DP_SDA("CPresencePluginData::ReadDocumentIdL - 2");
+ // If document id lenght is zero (KNullDesC8) or error
+ // is KErrNotFound leave with KErrNotFound
+ User::Leave( KErrNotFound );
+ }
+ else
+ {
+ User::Leave( error );
+ }
+
+ CleanupStack::PopAndDestroy( &documentId );
+ CleanupStack::PopAndDestroy(); //settings
+
+ DP_SDA("CPresencePluginData::ReadDocumentIdL OUT");
+ }
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::DeletePresenceVariablesL()
+// ---------------------------------------------------------------------------
+//
+void CPresencePluginData::DeletePresenceVariablesL( const TInt aServiceId )
+ {
+ DP_SDA("CPresencePluginData::DeletePresenceVariablesL IN");
+ DP_SDA2(" -> aServiceId: %d", aServiceId );
+
+ MVIMPSTSettingsStore* settings = CVIMPSTSettingsStore::NewLC();
+
+ // Reset availability value in uiservicetabsettings
+ User::LeaveIfError( settings->SetL(
+ aServiceId, EServicePresenceAvailablilityValue, KErrNotFound ) );
+
+ // Reset status message in uiservicetabsettings
+ User::LeaveIfError( settings->SetL(
+ aServiceId, EServiceCustomStatusMessage, KNullDesC ) );
+
+ // Reset document id value in uiservicetabsettings
+ User::LeaveIfError( settings->SetL(
+ aServiceId, EServicePresenceSessionIdentifier, KNullDesC8 ) );
+
+ CleanupStack::PopAndDestroy(); // settings
+
+ DP_SDA("CPresencePluginData::DeletePresenceVariablesL OUT");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::ResolveNoteElementL
+// Returns <note> element corresponding current locale or first <note>
+// element if better match is not found.
+// ---------------------------------------------------------------------------
+//
+MSimpleElement* CPresencePluginData::ResolveNoteElementL(
+ const RPointerArray<MSimpleElement>& aElements ) const
+ {
+ DP_SDA("CPresencePluginData::ResolveNoteElementL" )
+
+ MSimpleElement* bestMatch = NULL;
+ MSimpleElement* secondBestMatch = NULL;
+
+ for ( TInt i = aElements.Count() - 1; i >= 0 && NULL == bestMatch; i-- )
+ {
+ MSimpleElement* element = aElements[i];
+
+ using namespace NPresencePlugin::NPresence;
+ if ( 0 == element->LocalName().CompareF( KPresenceNote8 ) )
+ {
+ if ( IsElementLanguageValidForCurrentLocaleL( *element ) )
+ {
+ DP_SDA("CPresencePluginData::ResolveNoteElementL, BEST MATCH.")
+ bestMatch = element;
+ }
+ else
+ {
+ secondBestMatch = element;
+ }
+ }
+ }
+
+ return ( bestMatch ? bestMatch : secondBestMatch );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CPresencePluginData::IsElementLanguageValidForCurrentLocaleL
+// ---------------------------------------------------------------------------
+//
+TBool CPresencePluginData::IsElementLanguageValidForCurrentLocaleL(
+ MSimpleElement& aElement ) const
+ {
+ DP_SDA( "CPresencePluginData::IsElementLanguageValidForCurrentLocaleL" )
+
+ TBool isLanguageResolved = EFalse;
+ _LIT8( KLanguageAttribute, "xml:lang" );
+
+ TLanguage language = User::Language();
+ RPointerArray<MSimpleAttribute> attributes;
+ CleanupClosePushL( attributes );
+ aElement.SimpleAttributesL( attributes );
+ for ( TInt i = attributes.Count() - 1; i >= 0 && !isLanguageResolved; i-- )
+ {
+ if ( 0 == KLanguageAttribute().CompareF( attributes[i]->Name() ) )
+ {
+ const TDesC8& attributeValue = attributes[i]->Value();
+ for ( TInt index = 0; index < KLanguageCodeMappingsCount; index++ )
+ {
+ if ( language == KLanguageCodeMappings[index].SymbianLanguageCode() &&
+ 0 == attributeValue.CompareF(
+ KLanguageCodeMappings[index].IsoLanguageCode() ) )
+ {
+ isLanguageResolved = ETrue;
+ }
+ }
+ }
+ }
+ CleanupStack::Pop( &attributes );
+
+ return isLanguageResolved;
+ }
+
+// End of file