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

#ifndef OB_SERVANT_BASE_H
#define OB_SERVANT_BASE_H

#include <OB/TypeCodeConst.h>
#include <OB/POAServantBase_fwd.h>
#include <OB/Object_fwd.h>
#include <OB/POAInterface_fwd.h>
#include <OB/Upcall_fwd.h>
#include <OB/DirectStubImpl_fwd.h>
#include <OB/IFR2_fwd.h>
#include <OB/OBPOAManager_fwd.h>
#include <OB/Stream_fwd.h>

#include <OB/PIArgs.h>

#include <OB/Basic.h>
#include <OB/Except.h>

namespace CORBA
{

class ServerRequest; // For the friend declaration

//
// RepositoryId
//
typedef char* RepositoryId;

} // End of namespace CORBA

namespace PortableServer
{

//
// ObjectId
//  
class OBUnique_ObjectId;
typedef OB::FixSeq< CORBA::Octet, OBUnique_ObjectId > ObjectId;
typedef OB::SeqVar< OB::FixSeq< CORBA::Octet, OBUnique_ObjectId > >
    ObjectId_var;

//
// Conversion between ObjectId and string/wstring
//
char* ObjectId_to_string(const ObjectId&);
CORBA::WChar* ObjectId_to_wstring(const ObjectId&);

ObjectId* string_to_ObjectId(const char*);
ObjectId* wstring_to_ObjectId(const CORBA::WChar*);

//
// The PortableServer::ServantBase class, as defined by the C++
// mapping
//
class ServantBase : public virtual OB::RefCountable
{

#ifdef __SUNPRO_CC
    //
    // COMPILERFIX: Dummy data member to get around Forte 6.0 bug with
    // virtual inheritance
    //
    int dummy_;
#endif

protected:

    //
    // Dispatch operations of the base interface
    //
    void _OB_dispatchBase(OB::Upcall_ptr);

    //
    // Find an operation
    //
    static CORBA::Long _OB_findOperation(OB::Upcall_ptr, const char*[],
					 CORBA::ULong);

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

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

    //
    // Set the argument information
    //
    static void _OB_setArgDesc(OB::Upcall_ptr,
			OB::ParameterDesc*, CORBA::ULong,
			OB::ParameterDesc*,
			CORBA::TypeCode_ptr*, CORBA::ULong);

    //
    // The DSI needs access to the protected members
    //
    friend class ::CORBA::ServerRequest;

    ServantBase() { }
    ServantBase(const ServantBase&) { }
    ServantBase& operator=(const ServantBase&) { return *this; }
    
public:
    
    virtual ~ServantBase() { }
    
    virtual POA_ptr _default_POA();
    
    virtual CORBA::InterfaceDef_ptr _get_interface()
        throw(CORBA::SystemException);
        
    virtual CORBA::Boolean _is_a(const char* logical_type_id)
        throw(CORBA::SystemException);
        
    virtual CORBA::Boolean _non_existent()
        throw(CORBA::SystemException);

    virtual CORBA::RepositoryId _primary_interface(const ObjectId&,
						   POA_ptr) = 0;
        
    virtual void _add_ref() { }
    virtual void _remove_ref() { }
    
    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
    virtual void _OB_dispatch(OB::Upcall_ptr) = 0;

    CORBA::Object_ptr _OB_createReference();
    virtual OB::DirectStubImpl_ptr _OB_createDirectStubImpl(POA_ptr,
							    const ObjectId&);
    virtual CORBA::ULong _OB_getRefCount();
};

//
// The PortableServer::RefCountServantBase class, as defined by the
// C++ mapping.
//
class RefCountServantBase : public virtual ServantBase,
                            public virtual OB::RefCount
{
protected:
    
    RefCountServantBase() { }
    RefCountServantBase(const RefCountServantBase&) { }
    RefCountServantBase&
    operator=(const RefCountServantBase&) { return *this; }

public:
    
    virtual void _add_ref();
    virtual void _remove_ref();
    virtual CORBA::ULong _OB_getRefCount();
};

} // End of namespace PortableServer

#endif
