// **********************************************************************
//
// Copyright (c) 2002
// IONA Technologies, Inc.
// Waltham, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_MARSHAL_STUB_IMPL_H
#define OB_MARSHAL_STUB_IMPL_H

#include <OB/MarshalStubImpl_fwd.h>
#include <OB/Client_fwd.h>
#include <OB/Downcall_fwd.h>

#include <OB/DII_fwd.h>
#include <OB/NamedValue_fwd.h>
#include <OB/StubImpl.h>
#include <OB/list.h>

#include <OB/OBObject.h> // TODO: This isn't really needed by this header

namespace OB
{

//
// A sequence of clients
// 
typedef ObjSeq< Client, int > ClientSeq;
typedef SeqVar< ClientSeq > ClientSeq_var;

//
// A sequence of profiles
// 
typedef ObjSeq< RefCountProfileInfo, int > RefCountProfileInfoSeq;
typedef SeqVar< RefCountProfileInfoSeq > RefCountProfileInfoSeq_var;

//
// Declare ParameterDesc
//
struct ParameterDesc;

//
// The MarshalStubImpl class
//
class MarshalStubImpl : virtual public StubImplBase, public JTCMutex
{
    //
    // Hide copy-constructor and assignment operator
    //
    MarshalStubImpl(const MarshalStubImpl&);
    void operator=(const MarshalStubImpl&);

    //
    // The ORBInstance object
    //
    ORBInstance_var orbInstance_;

    //
    // The IOR and the original IOR
    //
    RefCountIOR_var IOR_;
    RefCountIOR_var origIOR_;

    //
    // The list of policies
    //
    RefCountPolicyList_var policies_;

    //
    // All client/profile pairs
    //
    OB_STL::list<ClientProfilePair_var>* clientProfilePairs_;

    //
    // Get a client/profile pair
    //
    Client_ptr getClientProfilePair(RefCountProfileInfo_out);

protected:

    //
    // Operations to create new Downcall objects
    //
    Downcall_ptr _OB_createDowncall(const char*, bool);
    Downcall_ptr _OB_createLocateRequestDowncall();
    Downcall_ptr _OB_createPIArgsDowncall(const char*, bool, ParameterDesc[],
					  CORBA::ULong, ParameterDesc*,
					  CORBA::TypeCode_ptr*, CORBA::ULong);
    Downcall_ptr _OB_createPIDIIDowncall(const char*, bool, CORBA::NVList_ptr,
					 CORBA::NamedValue_ptr,
					 CORBA::ExceptionList_ptr);

    //
    // Marshalling interception points
    //
    static OutputStream_ptr _OB_preMarshal(Downcall_ptr);
    static void _OB_marshalEx(Downcall_ptr, const CORBA::SystemException&);
    static void _OB_postMarshal(Downcall_ptr);

    //
    // Methods to invoke requests and pick up replies
    //
    static void _OB_locate(Downcall_ptr);
    static void _OB_request(Downcall_ptr);
    static void _OB_oneway(Downcall_ptr);
    static void _OB_deferred(Downcall_ptr);
    static void _OB_response(Downcall_ptr);
    static bool _OB_poll(Downcall_ptr);

    //
    // Unmarshalling interception points
    //
    static InputStream_ptr _OB_preUnmarshal(Downcall_ptr);
    static InputStream_ptr _OB_preUnmarshal(Downcall_ptr, bool&);
    static void _OB_unmarshalEx(Downcall_ptr, const CORBA::SystemException&);
    static void _OB_postUnmarshal(Downcall_ptr);

    //
    // Operations for handling user exceptions
    //
    static char* _OB_unmarshalExceptionId(Downcall_ptr);
    static void _OB_setUserException(Downcall_ptr, CORBA::UserException*,
				     const char*);
    static void _OB_setUserException(Downcall_ptr,
				     const CORBA::UserException&);

    //
    // Handle a FailureException
    //
    void _OB_handleFailureException(Downcall_ptr, const FailureException&);

    //
    // The DII needs access to the protected members
    //
    friend class ::CORBA::Request;

public:

    MarshalStubImpl();
    virtual ~MarshalStubImpl();

    static inline MarshalStubImpl_ptr _duplicate(MarshalStubImpl_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline MarshalStubImpl_ptr _nil()
    { return 0; }

    virtual CORBA::InterfaceDef_ptr _get_interface();
    virtual CORBA::Boolean _is_a(const char*);
    virtual CORBA::Boolean _non_existent();
    virtual CORBA::Boolean _locate_request();
 
    virtual OCI::ConnectorInfo_ptr _get_oci_connector_info();
    virtual OCI::TransportInfo_ptr _get_oci_transport_info();

    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
    void _OB_setup(ORBInstance_ptr, RefCountIOR_ptr, RefCountIOR_ptr,
                   RefCountPolicyList_ptr);
};

} // End of namespace OB

namespace CORBA
{

inline void
release(OB::MarshalStubImpl_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline Boolean
is_nil(OB::MarshalStubImpl_ptr p)
{
    return p == 0;
}

} // End of namespace CORBA

#endif
