// ----------------------------------------------------------------------------
// FILE NAME: iobservr.hpp
//
// DESCRIPTION:
//   Declaration of the classes:
//     IObserver
//     IObserverConnectionTo
//
// COPYRIGHT:
//   IBM Open Class Library
//   Licensed Material - Property of IBM
//   (C) Copyright IBM Corp. 1992, 1997  All Rights Reserved.
//
//
// Revision: 46 1.10.1.3 source/core/base/iobservr.hpp, notification, ioc.v400, 980918 
// ----------------------------------------------------------------------------

#ifndef _IOBSERVR_
#define _IOBSERVR_

#include <ibase.hpp>
#include <ievtdata.hpp>
#include <inotify.hpp>
#include <iintrst.hpp>
#include <inotifev.hpp>
#include <ikeyset2.h>

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

class INotificationEvent;
class INotifier;
class IObserverData;
class INotificationProcessor;
class IRequestProcessor;
class IThreadId;
class IRequestHandler;
class IRequestProcessorDict;

#pragma pack(push,4)
#pragma enum(4)

class IObserver
{
public:
    // ------------------------------ Constructors ----------------------------
    virtual             ~IObserver( );

    // ---------------------------- Notifier Attachment -----------------------
    virtual IObserver&  handleNotificationsFor(         INotifier&  notifier,
                                                const IEventData&   userData = IEventData());

    //
    // Register this observer to handle notifications for the specified interest.
    virtual IObserver&  handleNotificationsFor(IInterest&);

    virtual IObserver&  handleNotificationsFor(INotifier&,const INotificationId& id);

    virtual IObserver&  stopHandlingNotificationsFor(INotifier& notifier);

    virtual IObserver& stopHandlingNotificationsFor(const IInterest&);

    virtual IObserver& stopHandlingNotificationsFor(INotifier&,const INotificationId& id);

    const IThreadId& threadId() const;

    //For InternalUseOnly
public:
    INotificationProcessor* requestProcessor();

protected:
    // --------------------------- Event Dispatching --------------------------
    virtual IObserver&  dispatchNotificationEvent(const INotificationEvent& event) = 0;

    // ------------------------------- Constructors ---------------------------
    IObserver( );

private:
    // -------------------------------- Friends -------------------------------
    friend class INotifier;
    friend class IObserverList;
    friend class INotificationRequest;


    // ------------------------------ Private Data ----------------------------
    IRequestProcessor& setRequestProcessor();
    INotificationProcessor* fRequestProcessor;
    IThreadId fThreadId;
    static IRequestProcessorDict* fRequestProcessorDict;
    IObserverData* fObserverData;
};


//Helper class for a Cross Thread  Observer. Starts the notification dispatch loop
class ICrossThreadNotificationLoop
{
public:
                    ICrossThreadNotificationLoop(IObserver&);
    virtual         ~ICrossThreadNotificationLoop ();

    virtual void    run();
    virtual void    stop();

protected:
    virtual void    dispatchNotification();
    virtual void    waitAndDispatchNotification();
    bool            observersInCurrentThread();
    void            cleanup();

private:
                    ICrossThreadNotificationLoop(const ICrossThreadNotificationLoop& copy);
                    ICrossThreadNotificationLoop& operator=(const ICrossThreadNotificationLoop& rhs);

    IObserver&              fObserver;
    IRequestHandler*        fRequestHandler;
    INotificationProcessor* fRequestProcessor;
    bool                    fIsRunning;
};


//---------------------- Collection Class Key Function -------------------------
const IThreadId& key(const INotificationProcessor* object);

//IObserverConnectionTo
template <class ATarget> class IObserverConnectionTo : public IObserver
{
    typedef IObserver Inherited;
public:
    // ----------------------------- Type Definitions -------------------------
    typedef void (ATarget::*MemberFunction)(const INotificationEvent&);

    // ------------------------------- Constructors ---------------------------
    IObserverConnectionTo(ATarget&       target,
                          MemberFunction memberFunction);

    virtual ~IObserverConnectionTo();

protected:
    // ----------------------------- Event Dispatching ------------------------
    virtual IObserverConnectionTo<ATarget>
                        &dispatchNotificationEvent(const INotificationEvent& event);

private:
    // --------------------------------- Hidden -------------------------------
    IObserverConnectionTo(const IObserverConnectionTo<ATarget>& copy);
  IObserverConnectionTo<ATarget>& operator= (const IObserverConnectionTo<ATarget>& rhs);

    // -------------------------------- Private data --------------------------
    ATarget& fTarget;

    MemberFunction fConnectedMember;
};


class IObserverForConnectionToImp
{
public:
                    IObserverForConnectionToImp();
    virtual         ~IObserverForConnectionToImp();

    virtual void    handleOldNotificationEvent(const INotificationEvent& event);

private:
    IObserverForConnectionToImp(const IObserverForConnectionToImp& copy);
    IObserverForConnectionToImp& operator=(const IObserverForConnectionToImp& rhs);

    virtual void    dispatchOldNotificationEvent(const INotificationEvent&  event,
                                                        void*               edata) = 0;
};


//class IObserverForConnectionTo
template <class AType, class ATarget> class IObserverForConnectionTo :
    public IObserver, private IObserverForConnectionToImp
{
public:
    // ----------------------------- Type Definitions -------------------------
    typedef void (ATarget::*MemberFunction)(const INotificationEventFor<AType>& event);

    // ------------------------------- Constructors ---------------------------
                    IObserverForConnectionTo(   ATarget&       target,
                                                                            MemberFunction memberFunction);

    virtual         ~IObserverForConnectionTo();

protected:
    // ----------------------------- Event Dispatching ------------------------
    virtual IObserverForConnectionTo<AType,ATarget>&
                    dispatchNotificationEvent(const INotificationEvent& event);

private:
    // -------------------------------- Hidden --------------------------------
    IObserverForConnectionTo(const IObserverForConnectionTo<AType,ATarget>& copy);
    IObserverForConnectionTo<AType,ATarget>& operator=(const IObserverForConnectionTo<AType,ATarget>& rhs);

    // ------------------------------ Inherited -------------------------------
    virtual void dispatchOldNotificationEvent ( const INotificationEvent& event, void* edata);

    // ---------------------------- Private Data  -----------------------------
    ATarget& fTarget;
    MemberFunction fConnectedMember;
};

#pragma enum(pop)
#pragma pack(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#include <iobservr.inl>

#endif
