presencefwsimpleadpt/src/simplepluginpublisher.cpp
changeset 0 c8caa15ef882
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/presencefwsimpleadpt/src/simplepluginpublisher.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,1071 @@
+/*
+* Copyright (c) 2006 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:    SIMPLE Protocol implementation for Presence Framework
+*
+*/
+
+
+
+
+#include <e32std.h>
+#include <utf.h>
+
+#include <personpresenceinfo.h>
+#include <presenceinfo.h>
+#include <presenceinfofield.h>
+#include <presenceinfofieldcollection.h>
+#include <presenceinfofieldvaluetext.h>
+#include <presenceinfofieldvalueenum.h>
+#include <presenceinfofieldvaluebinary.h>
+#include <presenceobjectfactory.h>
+#include <presencewatcherinfo.h>
+#include <presenceerrors.hrh>
+
+#include <servicepresenceinfo.h>
+#include <devicepresenceinfo.h>
+
+#include <protocolpresencedatahost.h>
+#include <protocolpresencepublishingdatahost.h>
+
+#include <ximpdatasubscriptionstate.h>
+#include <ximperrors.hrh>
+#include <ximpidentity.h>
+#include <ximpobjectcollection.h>
+#include <ximpobjectfactory.h>
+#include <ximpprotocolconnectionhost.h>
+#include <ximpstatus.h>
+
+#include <simplefactory.h>
+
+#include <msimplewinfo.h>
+#include <msimplepublisher.h>
+#include <msimplewatcher.h>
+#include <msimpledocument.h>
+#include <msimpleelement.h>
+#include <msimplecontent.h>
+
+#include "simpleplugincommon.h"
+#include "simplepluginpublisher.h"
+#include "simpleplugindebugutils.h"
+#include "simpleutils.h"
+#include "simplepluginwinfo.h"
+#include "simpleplugindata.h"
+#include "simplepluginxdmutils.h"
+#include "simplepluginconnection.h"
+
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// -----------------------------------------------------------------------------
+// CSimplePluginWatcherInfo::CSimplePluginWatcherInfo
+// -----------------------------------------------------------------------------
+CSimplePluginWatcherInfo::CSimplePluginWatcherInfo( )
+        {}
+
+// -----------------------------------------------------------------------------
+// CSimplePluginWatcherInfo::~CSimplePluginWatcherInfo
+// -----------------------------------------------------------------------------
+CSimplePluginWatcherInfo::~CSimplePluginWatcherInfo()
+    {
+    delete iId;
+    delete iSipId;
+    }
+
+// ----------------------------------------------------------
+// CSimplePluginWatcherInfo::NewL
+// ----------------------------------------------------------
+//
+CSimplePluginWatcherInfo* CSimplePluginWatcherInfo::NewL(
+   const TDesC8& aId, const TDesC& aSipId )
+    {
+    CSimplePluginWatcherInfo* self = new (ELeave) CSimplePluginWatcherInfo( );
+    CleanupStack::PushL( self );
+    self->ConstructL( aId, aSipId );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ----------------------------------------------------------
+// CSimplePluginWatcherInfo::ConstructL
+// ----------------------------------------------------------
+//
+void CSimplePluginWatcherInfo::ConstructL(
+    const TDesC8& aId, const TDesC& aSipId  )
+    {
+    iId = aId.AllocL();
+    iSipId = aSipId.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginWatcherInfo::Destroy
+// -----------------------------------------------------------------------------
+void CSimplePluginWatcherInfo::Destroy()
+    {
+    iLink.Deque();
+    delete this;
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginWatcherInfo::Match
+// -----------------------------------------------------------------------------
+TBool CSimplePluginWatcherInfo::Match( const TDesC8& aId, const TDesC& aSipId )
+    {
+    if ( (!iId->Des().CompareF( aId )) && (!iSipId->Des().CompareF( aSipId)) )
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginWatcherInfo::SipId
+// -----------------------------------------------------------------------------
+TPtrC CSimplePluginWatcherInfo::SipId( )
+    {
+    return iSipId ? iSipId->Des() : TPtrC();
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::CSimplePluginPublisher
+// ---------------------------------------------------------------------------
+//
+CSimplePluginPublisher::CSimplePluginPublisher(
+    MSimplePluginSettings& aConnSets,
+    MSimplePluginConnectionObs& aObs,
+    MSimpleConnection& aConn )
+: CActive( CActive::EPriorityStandard ),
+  iConnObs(aObs), iConnSets( aConnSets), iConnection(aConn),
+  iSubscribed(EFalse), iSubscribedOwn(EFalse), iPublished(EFalse),
+  iWatcherList( CSimplePluginWatcherInfo::LinkOffset())
+    {
+    CActiveScheduler::Add(this);
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::ConstructL( )
+    {
+    iPublisher = TSimpleFactory::NewPublisherL( iConnection, *this );
+    iWatcher = TSimpleFactory::NewWatcherL( iConnection, *this );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::NewL
+// ---------------------------------------------------------------------------
+//
+CSimplePluginPublisher* CSimplePluginPublisher::NewL(
+    MSimplePluginSettings& aConnSets,
+    MSimplePluginConnectionObs& aObs,
+    MSimpleConnection& aConn )
+    {
+    CSimplePluginPublisher* self =
+        new( ELeave ) CSimplePluginPublisher( aConnSets, aObs, aConn );
+    CleanupStack::PushL( self );
+    self->ConstructL(  );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::~CSimplePluginPublisher
+// ---------------------------------------------------------------------------
+//
+CSimplePluginPublisher::~CSimplePluginPublisher()
+    {
+    if ( iDocument )
+        {
+        iDocument->Close();
+        }
+
+    if ( iPublisher )
+        {
+        iPublisher->Close();
+        }
+
+    if ( iWatcher )
+        {
+        iWatcher->Close();
+        }
+
+    // delete iWatchers;
+    DeleteWatchers();
+
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginPublisher::DeleteWatchers
+// -----------------------------------------------------------------------------
+void CSimplePluginPublisher::DeleteWatchers()
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DeleteWatchers" ) );
+#endif
+    // Delete all buffered transaction requests
+    TDblQueIter<CSimplePluginWatcherInfo> rIter( iWatcherList );
+    rIter.SetToFirst();
+
+    while ( rIter )
+        {
+        CSimplePluginWatcherInfo* w = rIter;
+        rIter++;
+        // delete wathcer info
+        w->Destroy();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginPublisher::AddWatcherIfNotExistsL
+// -----------------------------------------------------------------------------
+void CSimplePluginPublisher::AddWatcherIfNotExistsL( const TDesC8& aId, const TDesC& aSipId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: AddWatcherIfNotExistsL" ) );
+#endif
+    TDblQueIter<CSimplePluginWatcherInfo> rIter( iWatcherList );
+    rIter.SetToFirst();
+
+    TBool found(EFalse);
+
+    while ( rIter )
+        {
+        CSimplePluginWatcherInfo* w = rIter;
+        rIter++;
+        found = w->Match( aId, aSipId );
+        if ( found )
+            {
+            break;
+            }
+        else
+            {
+            // continue searching
+            }
+        }
+    if ( !found )
+        {
+#ifdef _DEBUG
+        PluginLogger::Log(_L("PluginPublisher: AddWatcherIfNotExistsL adds a watcher" ) );
+#endif
+        CSimplePluginWatcherInfo* w = CSimplePluginWatcherInfo::NewL( aId, aSipId );
+        iWatcherList.AddLast( *w );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSimplePluginPublisher::RemoveWatcherIfExistsL
+// -----------------------------------------------------------------------------
+void CSimplePluginPublisher::RemoveWatcherIfExistsL( const TDesC8& aId, const TDesC& aSipId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: RemoveWatcherIfExistsL" ) );
+#endif
+    TDblQueIter<CSimplePluginWatcherInfo> rIter( iWatcherList );
+    rIter.SetToFirst();
+
+    TBool found(EFalse);
+
+    while ( rIter )
+        {
+        CSimplePluginWatcherInfo* w = rIter;
+        rIter++;
+        // delete wathcer info
+        found = w->Match( aId, aSipId );
+        if ( found )
+            {
+#ifdef _DEBUG
+            PluginLogger::Log(_L("PluginPublisher: RemoveWatcherIfExistsL removes a watcher" ) );
+#endif
+            w->Destroy();
+            break;
+            }
+        else
+            {
+            // continue searching
+            }
+        }
+    }
+// -----------------------------------------------------------------------------
+// CSimplePluginPublisher::MakeCurrentWatcherListLC
+// -----------------------------------------------------------------------------
+CDesCArrayFlat* CSimplePluginPublisher::MakeCurrentWatcherListLC()
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: MakeCurrentWatcherListL" ) );
+#endif
+    // No one should be added more than once
+    const TInt KMyGran = 10;
+    CDesCArrayFlat* watchers = new (ELeave) CDesCArrayFlat( KMyGran );
+    CleanupStack::PushL( watchers );      // << watchers
+
+    // add user only once here.
+    TDblQueIter<CSimplePluginWatcherInfo> rIter( iWatcherList );
+    rIter.SetToFirst();
+
+    while ( rIter )
+        {
+        CSimplePluginWatcherInfo* w = rIter;
+        rIter++;
+
+        TInt dummy = 0;
+        if ( watchers->Find( w->SipId(), dummy ))
+            {
+            watchers->AppendL( w->SipId() );
+            }
+        else
+            {
+            // continue searching
+            }
+        }
+
+    return watchers;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoPublishOwnPresenceL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoPublishOwnPresenceL(
+    const MPresenceInfo& aOwnPresence,
+    TXIMPRequestId aReqId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoPublishOwnPresenceL"));
+#endif
+
+    const MPersonPresenceInfo* persInfo = aOwnPresence.PersonPresence();
+
+    // convert data format from PrFW to internal
+    if ( !persInfo )
+        {
+        // Notice: error codes
+        CompletePrFwReq( KErrArgument );
+        return;
+        }
+    InitializeSimpleDocumentL( );
+    AddSimpleDocumentPersL( persInfo );
+
+    TInt myCount = aOwnPresence.ServicePresenceCount();
+    for ( TInt i=0; i < myCount; i++ )
+        {
+        const MServicePresenceInfo& servInfo = aOwnPresence.ServicePresenceAt(i);
+        AddSimpleDocumentServiceL( servInfo );
+        }
+    myCount = aOwnPresence.DevicePresenceCount();
+    for ( TInt i=0; i < myCount; i++ )
+        {
+        const MDevicePresenceInfo& devInfo = aOwnPresence.DevicePresenceAt(i);
+        AddSimpleDocumentDeviceL( devInfo );
+        }
+
+    // Ensure that XDM rules exists, the show continues in RunL
+    StartXdmOperationL(aReqId );
+    iOperation = EPublishOwn;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoSubscribeOwnPresenceL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoSubscribeOwnPresenceL(
+    const MPresenceInfoFilter& /*aPif*/,   // notice: aPif filter not supported
+    TXIMPRequestId aReqId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoSubscribeOwnPresenceL"));
+#endif
+
+    StartXdmOperationL( aReqId );
+
+    iOperation = ESubscribeOwn;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoUpdateOwnPresenceSubscriptionPifL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoUpdateOwnPresenceSubscriptionPifL(
+    const MPresenceInfoFilter& /*aPif*/,
+    TXIMPRequestId /*aReqId*/ )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoUpdateOwnPresenceSubscriptionPifL"));
+#endif
+    // Notice: aPif filter not supported
+    User::Leave( KErrNotSupported );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoUnsubscribeOwnPresenceL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoUnsubscribeOwnPresenceL(
+    TXIMPRequestId aReqId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoUnsubscribeOwnPresenceL"));
+#endif
+    iSubscribedOwn = EFalse;
+    TRAPD( err, iSimpleId = iWatcher->UnsubscribeL());
+    if ( err )
+        {
+        User::Leave( CSimplePluginConnection::HarmonizeErrorCode( err ));
+        }
+    iPrFwId = aReqId;
+    iOperation = EUnsubscribeOwn;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoSubscribePresenceWatcherListL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoSubscribePresenceWatcherListL(
+    TXIMPRequestId aReqId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoSubscribePresenceWatcherListL"));
+#endif
+
+    if ( !iSubscribed )
+        {
+        TRAPD( err, iConnObs.WinfoHandlerL()->SubscribeWinfoListL( aReqId ));
+        if ( err )
+            {
+            User::Leave( CSimplePluginConnection::HarmonizeErrorCode( err ));
+            }
+        iSubscribed = ETrue;
+        iPrFwId = aReqId;
+        iOperation = ESubscribeWinfo;
+        }
+    else
+        {
+        iPrFwId = aReqId;
+        CompletePrFwReq( KErrNone );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoUnsubscribePresenceWatcherListL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoUnsubscribePresenceWatcherListL(
+    TXIMPRequestId aReqId )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: DoUnsubscribePresenceWatcherListL"));
+#endif
+    if ( iSubscribed )
+        {
+        TRAPD( err, iConnObs.WinfoHandlerL()->UnsubscribeWinfoListL( aReqId ));
+        if ( err )
+            {
+            User::Leave( CSimplePluginConnection::HarmonizeErrorCode( err ));
+            }
+        iSubscribed = EFalse;
+        iPrFwId = aReqId;
+        iOperation = EUnsubscribeWinfo;
+        }
+    else
+        {
+        iPrFwId = aReqId;
+        CompletePrFwReq( KErrNone );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::PublishReqCompleteL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::PublishReqCompleteL( TInt /*aOpid*/, TInt aStatus )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: PublishReqCompleteL("));
+#endif
+    if ( !aStatus )
+        {
+        iPublished = ETrue;
+        }
+    else
+        {
+        }
+
+    CompletePrFwReq( aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::PublishTerminatedL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::PublishTerminatedL( TInt /*aOpid*/ )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: PublishTerminatedL"));
+#endif
+    // Notice: nothing to do now in Host APi.
+    iPublished = EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WatcherReqCompleteL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WatcherReqCompleteL( TInt /*aOpid*/, TInt aStatus )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: WatcherReqCompleteL"));
+#endif
+    if ( !aStatus )
+        {
+        iSubscribedOwn = ETrue;
+        }
+    else
+        {
+        }
+    CompletePrFwReq( aStatus );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WatcherNotificationL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WatcherNotificationL( MSimpleDocument& aDocument )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: WatcherNotificationL"));
+#endif
+
+    // Notice: Do not need to check the expiration here since WatcherTerminatedL
+    // is called then too.
+
+    MProtocolPresencePublishingDataHost& publishHost =
+        iConnObs.Host()->ProtocolPresenceDataHost().PublishingDataHost();
+    MPresenceInfo* prInfo = iConnObs.PresenceObjectFactory().NewPresenceInfoLC();  // << prInfo
+    CSimplePluginData::NotifyToPrInfoL( iConnObs.PresenceObjectFactory(), aDocument, *prInfo );
+
+#ifdef _DEBUG
+    // ---------------------------------------------------------
+    const MPersonPresenceInfo* pers_debug = prInfo->PersonPresence();
+    const MPresenceInfoFieldCollection& coll_debug = pers_debug->Fields();
+    TInt count_debug = coll_debug.FieldCount();
+    PluginLogger::Log(_L("PluginPublisher: nbr of fields received =%d"), count_debug );
+    // ---------------------------------------------------------
+#endif
+
+    // PrFw Host API callbacks
+
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: callback HandleSubscribedOwnPresenceL"));
+#endif
+    publishHost.HandleSubscribedOwnPresenceL( prInfo );
+    CleanupStack::Pop();  // >> prInfo
+
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WatcherListNotificationL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WatcherListNotificationL( MSimplePresenceList& /*aList*/ )
+    {
+    // Notice: not needed.
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WatcherTerminatedL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WatcherTerminatedL(
+    TInt /*aOpId*/, TInt /*aReason*/ )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: WatcherTerminatedL"));
+#endif
+    iSubscribedOwn = EFalse;
+
+    MProtocolPresencePublishingDataHost& publishHost =
+        iConnObs.Host()->ProtocolPresenceDataHost().PublishingDataHost();
+    MXIMPDataSubscriptionState *state = iConnObs.ObjectFactory().NewDataSubscriptionStateLC();
+    MXIMPStatus* status = iConnObs.ObjectFactory().NewStatusLC();
+    state->SetSubscriptionStateL( MXIMPDataSubscriptionState::ESubscriptionInactive );
+    status->SetResultCode( KErrCompletion );
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: callback SetOwnPresenceDataSubscriptionStateL"));
+#endif
+    publishHost.SetOwnPresenceDataSubscriptionStateL( state, status );
+    CleanupStack::Pop( 2 ); // status, state
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::CompletePrFwReq
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::CompletePrFwReq( TInt aStatus )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: CompletePrFwReq status=%d"), aStatus );
+#endif
+    if ( iOperation != ENoOperation )
+        {
+        iOperation = ENoOperation;
+        iConnObs.CompleteReq( iPrFwId, aStatus );
+        iPrFwId = TXIMPRequestId();
+        }
+    else
+        {
+        }
+    return;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoCancel
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoCancel(  )
+    {
+    iXdmUtils->Cancel();
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::RunL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::RunL(  )
+    {
+
+    TInt status = iStatus.Int();
+
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: RunL %d"), status );
+#endif
+
+    if ( !status )
+        {
+        if ( iOperation == ESubscribeOwn )
+            {
+            iSimpleId = iWatcher->SubscribeL(
+                iConnSets.CurrentSipPresentity8(),
+                NULL,  // aFilter <-> aPif
+                ETrue, EFalse );
+            }
+        else
+            {
+            MakePublishReqL();
+            }
+        }
+    else
+        {
+        CompletePrFwReq( status );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::RunError
+// ---------------------------------------------------------------------------
+//
+TInt CSimplePluginPublisher::RunError( TInt aError )
+    {
+    CompletePrFwReq( aError );
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::GetInterface
+// ---------------------------------------------------------------------------
+//
+TAny* CSimplePluginPublisher::GetInterface(
+        TInt32 aInterfaceId,
+        TIfGetOps aOptions )
+    {
+    if ( aInterfaceId == GetInterfaceId() )
+        {
+        // caller wants this interface
+        MProtocolPresencePublishing* myIf = this;
+        return myIf;
+        }
+    else if ( aOptions == MXIMPBase::EPanicIfUnknown )
+        {
+        User::Panic( _L("CSimplePlugin"), KErrExtensionNotSupported );
+        }
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::GetInterface
+// ---------------------------------------------------------------------------
+//
+const TAny* CSimplePluginPublisher::GetInterface(
+    TInt32 aInterfaceId,
+    TIfGetOps aOptions ) const
+    {
+    if ( aInterfaceId == GetInterfaceId() )
+        {
+        // caller wants this interface
+        const MProtocolPresencePublishing* myIf = this;
+        return myIf;
+        }
+    else if ( aOptions == MXIMPBase::EPanicIfUnknown )
+        {
+        User::Panic( _L("CSimplePlugin"), KErrExtensionNotSupported );
+        }
+    return NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::GetInterfaceId
+// ---------------------------------------------------------------------------
+//
+TInt32 CSimplePluginPublisher::GetInterfaceId() const
+    {
+    return MProtocolPresencePublishing::KInterfaceId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::InitializeSimpleDocumentL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::InitializeSimpleDocumentL( )
+    {
+    if ( iDocument )
+        {
+        iDocument->Close();
+        iDocument = NULL;
+        }
+    iDocument = TSimpleFactory::NewDocumentL();
+    iDocument->AddNamespaceL( KSimplePDM, KSimpleNsPDM );
+    iDocument->AddNamespaceL( KSimpleRPID, KSimpleNsRPID );
+    iDocument->AddNamespaceL( KSimpleOP, KSimpleNsOP );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::AddSimpleDocumentPersL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::AddSimpleDocumentPersL(
+    const MPersonPresenceInfo* aInfo )
+    {
+    CSimplePluginData::AddPrPersToSimpleDocumentL(
+        aInfo, *iDocument, iConnSets.CurrentSipPresentity8() );
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::AddSimpleDocumentServiceL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::AddSimpleDocumentServiceL(
+    const MServicePresenceInfo& aInfo )
+    {
+    if ( aInfo.Fields().FieldCount() > 0 || aInfo.ServiceType().Length() )
+        {
+        // Notice: currently all the fields in the namespace are supported,
+        // but this ensures that if namespace is extended later, it is
+        // handled right way in the adaptation
+        User::Leave( KPresenceErrPresenceInfoFieldTypeNotSupported );
+        }
+    else
+        {
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::AddSimpleDocumentDeviceL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::AddSimpleDocumentDeviceL(
+    const MDevicePresenceInfo& aInfo )
+    {
+    if ( aInfo.Fields().FieldCount() > 0 || aInfo.DeviceName().Length() )
+        {
+        // Notice: currently all the fields in the namespace are supported,
+        // but this ensures that if namespace is extended later, it is
+        // handled right way in the adaptation
+        User::Leave( KPresenceErrPresenceInfoFieldTypeNotSupported );
+        }
+    else
+        {
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::MakePublishReqL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::MakePublishReqL( )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: -> MakePublishReqL"));
+#endif
+    // Send the iDocument
+    if ( !iPublished )
+        {
+        iSimpleId = iPublisher->StartPublishL( *iDocument, ETrue );
+        }
+    else
+        {
+        iSimpleId = iPublisher->ModifyPublishL( *iDocument);
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::StartXdmOperationL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::StartXdmOperationL(
+    TXIMPRequestId aReqId )
+    {
+    TRAPD( err, DoStartXdmOperationL( aReqId ));
+    if ( err )
+        {
+        User::Leave( CSimplePluginConnection::HarmonizeErrorCode( err ));
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::DoStartXdmOperationL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::DoStartXdmOperationL(
+    TXIMPRequestId aReqId )
+    {
+    __ASSERT_DEBUG( !IsActive(), User::Leave( KErrCorrupt ) );
+    iPrFwId = aReqId;
+    if ( !iXdmUtils )
+        {
+        iXdmUtils = iConnObs.XdmUtilsL();
+        }
+    iXdmUtils->InitializeXdmL( iStatus );
+    SetActive();
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WinfoNotificationL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WinfoNotificationL(
+    MSimpleWinfo& aWinfo )
+    {
+    // ignore if not subscribed
+    if ( !iSubscribed )
+        {
+        return;
+        }
+
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: WinfoNotificationL"));
+#endif
+
+    // Handle full-state and partial state notifications
+    // - If terminated -> remove from iWatcherList
+    // - If active -> add into iWatcherList if does not already exist
+    // WinfoTerminatedL handles termination of subscription.
+
+    // Notice: CSimplePluginWinfo has completed the open request if needed before this.
+
+
+    /* example:
+
+    // active/pending/terminated
+
+   <?xml version="1.0"?>
+     <watcherinfo xmlns="urn:ietf:params:xml:ns:watcherinfo"
+   version="0" state="full">
+     <watcher-list resource="sip:presentity@example.com"
+                   package="presence">
+         <watcher status="active"
+            id="sr8fdsj"
+            duration-subscribed="509"
+            expiration="20"
+            event="approved">sip:watcherA@example.com"
+          </watcher>
+     */
+
+    RPointerArray<MSimpleElement> elems;
+    CleanupClosePushL( elems );         // << elems
+    TInt err = aWinfo.SimpleElementsL( elems );
+    User::LeaveIfError( err );
+    TInt count = elems.Count();
+
+    __ASSERT_DEBUG( count == 1, User::Leave( KErrCorrupt ) );
+
+    using namespace NSimplePlugin::NSimpleOma;
+
+    const TDesC8* stateVal = aWinfo.AttrValue( KSimpleState8 );
+    if ( stateVal && !stateVal->CompareF( KSimpleFull8 ))
+        {
+#ifdef _DEBUG
+        PluginLogger::Log(_L("PluginPublisher: fullstate = TRUE") );
+#endif
+        // full winfo-list is received
+        DeleteWatchers();
+        }
+  else
+        {
+#ifdef _DEBUG
+        PluginLogger::Log(_L("PluginPublisher: fullstate = FALSE") );
+#endif
+    }
+
+    MSimpleElement* elem = elems[0];
+    TPtrC8 p8 = elem->LocalName();
+    err = p8.CompareF( KSimpleWatcherList8 );
+    User::LeaveIfError( err );
+
+    err = elem->SimpleElementsL( elems );
+    User::LeaveIfError( err );
+
+    // Collect the active watchers only.
+    UpdateActiveWatchersListL( elems );
+
+    CDesCArrayFlat* watchers = MakeCurrentWatcherListLC();  // << watchers
+    MXIMPObjectCollection *actives =
+        iConnObs.ObjectFactory().NewObjectCollectionLC();                  // << actives
+
+    // Create MPresenceWatcherInfo entities for
+    // all active watchers and add to actives.
+    TInt wCount = watchers->MdcaCount();
+    for ( TInt j = 0; j < wCount; j++ )
+        {
+        // create MPresenceWatcherInfo object
+        MPresenceWatcherInfo* wInfo =
+            iConnObs.PresenceObjectFactory().NewPresenceWatcherInfoLC();           // << wInfo
+
+        MXIMPIdentity* identity = iConnObs.ObjectFactory().NewIdentityLC();  // << identity
+#ifdef _DEBUG
+        TBuf<200> debug_buffer;
+        debug_buffer = watchers->MdcaPoint( j );
+        PluginLogger::Log(_L("PluginPublisher: add watcher into collection: %S"), &debug_buffer);
+#endif
+        identity->SetIdentityL( watchers->MdcaPoint( j ) );
+        wInfo->SetWatcherIdL( identity );
+        CleanupStack::Pop( );                               // >> identity
+
+        wInfo->SetWatcherDisplayNameL( watchers->MdcaPoint( j ) );
+        wInfo->SetWatcherTypeL( MPresenceWatcherInfo::EPresenceSubscriber );
+
+        actives->AddObjectL( wInfo );
+        CleanupStack::Pop( );                           // >> wInfo
+        }
+
+    MProtocolPresencePublishingDataHost& publishHost =
+        iConnObs.Host()->ProtocolPresenceDataHost().PublishingDataHost();
+
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: callback HandlePresenceWatcherListL"));
+#endif
+    publishHost.HandlePresenceWatcherListL( actives );
+    CleanupStack::Pop();                            // >> actives
+    CleanupStack::PopAndDestroy( watchers );        // >> watchers
+    CleanupStack::PopAndDestroy( &elems );          // >> elems
+
+    }
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::WinfoTerminatedL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::WinfoTerminatedL( TInt /*aReason*/ )
+    {
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: WinfoTerminatedL") );
+#endif
+
+    if ( !iSubscribed )
+        {
+        return;
+        }
+
+    // call SetPresenceWatcherListDataSubscriptionStateL
+    iSubscribed = EFalse;
+
+    MProtocolPresencePublishingDataHost& publishHost =
+        iConnObs.Host()->ProtocolPresenceDataHost().PublishingDataHost();
+    MXIMPDataSubscriptionState *state = iConnObs.ObjectFactory().NewDataSubscriptionStateLC();
+    MXIMPStatus* status = iConnObs.ObjectFactory().NewStatusLC();
+    state->SetSubscriptionStateL( MXIMPDataSubscriptionState::ESubscriptionInactive );
+    state->SetDataStateL( MXIMPDataSubscriptionState::EDataUnavailable );
+    status->SetResultCode( KErrCompletion );
+#ifdef _DEBUG
+    PluginLogger::Log(_L("PluginPublisher: callback SetPresenceWatcherListDataSubscriptionStateL"));
+#endif
+    publishHost.SetPresenceWatcherListDataSubscriptionStateL( state, status );
+    CleanupStack::Pop( 2 ); // status, state
+    }
+
+
+// ---------------------------------------------------------------------------
+// CSimplePluginPublisher::UpdateActiveWatchersListL
+// ---------------------------------------------------------------------------
+//
+void CSimplePluginPublisher::UpdateActiveWatchersListL(
+    RPointerArray<MSimpleElement>& aElems )
+    {
+    // Collect active users.
+    using namespace NSimplePlugin::NSimpleOma;
+
+    HBufC* nodeContent = NULL;
+
+    TInt count = aElems.Count();
+
+    for ( TInt i = 0; i < count; i++ )
+        {
+        MSimpleElement* elem = aElems[i];
+        TPtrC8 p8( elem->LocalName());
+        if (!( p8.CompareF( KSimpleWatcher8 )))
+            {
+            const TDesC8* pp8 = elem->AttrValue( KSimpleStatus8 );
+            // Active wathers here
+            if ( pp8 && !pp8->CompareF( KSimpleActive8 ))
+                {
+
+                // save id since there may be multiple subscriptions
+                // from a single watcher SIP identity.
+                const TDesC8* pId8 = elem->AttrValue( KSimpleId8 );
+
+                // Build collection of grant requests
+                // Find the child node containing the SIP entity
+                nodeContent = elem->ContentUnicodeL();
+                CleanupStack::PushL( nodeContent );         // << nodeContent
+
+                AddWatcherIfNotExistsL( pId8 ? *pId8 : KNullDesC8, nodeContent->Des() );
+
+                CleanupStack::PopAndDestroy( nodeContent ); // >> nodeContent
+                }
+            // Terminated wathers here, remove them from active list
+            else if ( pp8 && !pp8->CompareF( KSimpleTerminated8 ))
+                {
+
+                const TDesC8* pId8 = elem->AttrValue( KSimpleId8 );
+
+                // Remove terminated from iWatcherList
+                nodeContent = elem->ContentUnicodeL();
+                CleanupStack::PushL( nodeContent );             // << nodeContent
+
+                RemoveWatcherIfExistsL( pId8 ? *pId8 : KNullDesC8, nodeContent->Des() );
+
+                CleanupStack::PopAndDestroy( nodeContent );     // >> nodeContent
+                }
+            }
+        }
+
+    }
+
+
+
+// End of file