//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / OVOPS++
//
//File: transporter.h
//
//Version: $Revision: 1.54 $
//
//State: $State: Exp $
//
//Date: $Date: 1998/10/19 08:46:02 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications Software and Multimedia
// 
//Authors:
//      Pasi Nummisalo
//      Timo Pärnänen
//      Jari Katajavuori
//	Timo Kokkonen
//	Vesa-Matti Puro
//
//Description:
//      This file contains an abstract base class (pfTransporter) for all
//	transporters and derived concrete transporter classes. These
//	concrete Transporter classes are described in the following text.
//
//	A Transporter is an implementation of the Visitor Pattern.
//      Visitor represents an operation to be performed on the elements
//      of an object structure. Visitor lets define a new operation without
//      changing the classes of the elements on which it operates.
//
//      A Message Transporter (pfMsgTransporter) is used to carry a
//	Messenger (pfMessenger) around a conduit graph. Usually it
//	originates either from a Adapter or from a Protocol.
//
//      An Install Transporter (pfInstallTransporter) is used to install
//	a conduit object to B side of the fist Mux it encounters. Usually
//	it originates from a Factory.
//
//      An Un-Install Transporter (pfUnInstallTransporter) is used to remove
//	a conduit object from B side of the first mux in encounters. Usually
//	it originates from TODO.
//
//      A Cross Connecter (pfCrossConnecter) is used to establish an
//	interconnection between two protocol conduits in different links.
//
//      A Close Request Transporter (pfCloseRequestTransporter) is used
//	to request a mux to send an Un-Install Transporter.
//
//	A Key Query Transporter (pfKeyQueryTransporter) is used to query
//	a mux if a specified key is allocated in its map or not.
//
//Copyright:   
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//      
//Licence:
//     
//
//History:
//
//
 
#ifndef __PF_TRANSPORTER_H__
#define __PF_TRANSPORTER_H__

class pfAdapter;
class pfFactory;
class pfMux;
class pfProtocol;
class pfState;

#include <typeinfo>
#include <string>

#include "pf/types.h"
#include "pf/conduit.h"
#include "pf/messenge.h"

class pfTransporter
{
    public:
        virtual ~pfTransporter(void);
        virtual pfTransporter *clone(void);

        virtual void atProtocol(pfProtocol *const protocol_, pfState *state_);
        virtual void atMux(pfMux *const mux_);
        virtual void atAdapter(pfAdapter *const adapter_);
        virtual void atFactory(pfFactory *const factory_);

        virtual bool isSender(pfConduit &candidate_);
        virtual void setSender(pfConduit &sender_);
        virtual void setSenderIsA(void);
        virtual void setSenderIsB(void);
        virtual void setSenderIsC(void);
        virtual bool isFromA(void) const;

        virtual void setKey(pfKey key_);
        virtual pfKey getKey(void) const;
        virtual pfKey getDispatchKey(string &keyName_) const;
        virtual bool isDispatchKeySet(string &keyName_) const;

        virtual bool acceptAsynchronous(void) const;
        virtual void setAcceptMethodToAsynchronous(void);
        virtual void setAcceptMethodToSynchronous(void);
        virtual void setSaveMethodToHead(void);
        virtual void setSaveMethodToTail(void);
        virtual bool saveAtTail(void) const;

        pfConduit _senderConduit;

        virtual string getName(void) const; // for trace
	virtual pfMessenger::SerialNumber getSerialNumber(void) const;
        
    protected:
        pfTransporter(void);
        pfTransporter(const pfTransporter &other_);
        pfKey _key;
        
    private:
        enum pfSender { SENDER_UNKNOWN, FROM_A, FROM_B, FROM_C };

        pfMessenger::SerialNumber _serialNumber;
        pfSender _sender;
        bool _asynchronous;
        bool _saveAtTail;
};

// ----------------------------------------------------------------------

class pfMsgTransporter : public pfTransporter 
{
    public:
        static pfMsgTransporter *createMsgTransporter(pfMessenger *messenger_);
        pfMsgTransporter(const pfMsgTransporter &other_);
        virtual ~pfMsgTransporter(void);
        virtual pfMsgTransporter *clone(void);

        virtual pfKey getDispatchKey(string &keyName_) const;
        virtual bool isDispatchKeySet(string &keyName_) const;

        virtual void atProtocol(pfProtocol *const protocol_,
                                pfState *state_);
        virtual void atMux(pfMux *const mux_);
        virtual void atAdapter(pfAdapter *const adapter_);
        virtual void atFactory(pfFactory *const factory_);
        
        pfMessenger *_messenger;

        virtual string getName(void) const; // for trace
	virtual pfMessenger::SerialNumber getSerialNumber(void) const;

    protected:
        pfMsgTransporter(void);
        explicit pfMsgTransporter(pfMessenger *messenger_);

    private:
};

// ----------------------------------------------------------------------
 
class pfInstallTransporter : public pfTransporter
{
    public:
        static pfInstallTransporter
            createInstallTransporter(pfConduit &conduit_);

        pfInstallTransporter(const pfInstallTransporter &other_);
        virtual ~pfInstallTransporter(void);
        virtual pfInstallTransporter *clone(void);

        virtual void atMux(pfMux *const mux_);
        void useThisKey(void);

    protected:
        pfInstallTransporter(pfConduit &conduit_);

    private:
        pfConduit _conduit;
        bool _useThisKey;
}; 

// ----------------------------------------------------------------------

class pfUnInstallTransporter : public pfTransporter
{
    public:
        static pfUnInstallTransporter
            createUnInstallTransporter(pfKey removeKey_);

        pfUnInstallTransporter(const pfUnInstallTransporter &other_);
        virtual ~pfUnInstallTransporter(void);
        virtual pfUnInstallTransporter *clone(void);

        virtual void atMux(pfMux *const mux_);
        virtual void atProtocol(pfProtocol *const protocol_,
                                pfState *state_);
        
    protected:
        pfUnInstallTransporter(pfKey removeKey_);

    private:
        pfKey _removeKey;
};

// ----------------------------------------------------------------------

class pfCrossConnecter : public pfTransporter
{
    public:
        static pfCrossConnecter createCrossConnector(void);
        virtual ~pfCrossConnecter(void);

        virtual bool isDispatchKeySet(string &keyName_) const;

        void setKeyName(string &keyName_);
        
        virtual void atMux(pfMux *const mux_);
        virtual void atFactory(pfFactory *const factory_);
        virtual void setOtherSide(pfConduit &otherSide_);
        virtual pfConduit getOtherSide(void);
        
    protected:
        pfCrossConnecter(void);

    private:
        pfConduit _otherSide;
        string _keyName;
};

// ----------------------------------------------------------------------

class pfCloseRequestTransporter : public pfTransporter
{
    public:
        static pfCloseRequestTransporter *createCloseRequestTransporter(void);
        pfCloseRequestTransporter(const pfCloseRequestTransporter &other_);
        virtual ~pfCloseRequestTransporter(void);
        virtual pfCloseRequestTransporter *clone(void);

        virtual void atMux(pfMux *const mux_);
        virtual void atProtocol(pfProtocol *const protocol_,
                                pfState *state_);

    protected:
        pfCloseRequestTransporter(void);
};

// ----------------------------------------------------------------------

class pfKeyQueryTransporter : public pfTransporter
{
    public:
        static pfKeyQueryTransporter createKeyQueryTransporter(pfKey key_);
        pfKeyQueryTransporter(const pfKeyQueryTransporter &other_);
        virtual ~pfKeyQueryTransporter(void);
        virtual pfKeyQueryTransporter *clone(void);

        virtual void atMux(pfMux *const mux_);

        virtual bool keyAllocatedStatus(void) const;

    protected:
        pfKeyQueryTransporter(void);

    private:
        bool _keyAllocatedStatus;
};

#endif // __PF_TRANSPORTER_H__

