// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_DII_H
#define OB_DII_H

//
// The ExceptionList class
//
class CORBA_ExceptionList;
typedef CORBA_ExceptionList* CORBA_ExceptionList_ptr;
typedef CORBA_ExceptionList_ptr ExceptionListRef;
void OBDuplicate(CORBA_ExceptionList_ptr);
void OBRelease(CORBA_ExceptionList_ptr);
typedef OBObjVar< CORBA_ExceptionList > CORBA_ExceptionList_var;

class CORBA_ExceptionList : public OBRefCount
{
    //
    // Hide copy-constructor and asignment operator
    //
    CORBA_ExceptionList(const CORBA_ExceptionList&);
    void operator=(const CORBA_ExceptionList&);

    OBObjSeq<CORBA_TypeCode> typeCodeSeq_;
    
protected:

    CORBA_ExceptionList() { };
    friend class CORBA_Request; // Requests may create ExceptionLists
    friend class CORBA_ORB;     // ORBs create ExceptionLists

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline CORBA_ExceptionList_ptr _duplicate(CORBA_ExceptionList_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline CORBA_ExceptionList_ptr _nil()
    { return 0; }

    CORBA_ULong count() const;
    
    void add(CORBA_TypeCode_ptr);
    void add_consume(CORBA_TypeCode_ptr);

    CORBA_TypeCode_ptr item(CORBA_ULong);

    CORBA_Status remove(CORBA_ULong);
};

inline void
CORBA_release(CORBA_ExceptionList_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(CORBA_ExceptionList_ptr p)
{
    return p == 0;
}

//
// The ContextList class
//
class CORBA_ContextList;
typedef CORBA_ContextList* CORBA_ContextList_ptr;
typedef CORBA_ContextList_ptr ContextListRef;
void OBDuplicate(CORBA_ContextList_ptr);
void OBRelease(CORBA_ContextList_ptr);
typedef OBObjVar< CORBA_ContextList > CORBA_ContextList_var;

class CORBA_ContextList : public OBRefCount
{
    //
    // Hide copy-constructor and asignment operator
    //
    CORBA_ContextList(const CORBA_ContextList&);
    void operator=(const CORBA_ContextList&);

    OBStrSeq stringSeq_;

protected:

    CORBA_ContextList() { };
    friend class CORBA_Request; // Requests may create ContextLists
    friend class CORBA_ORB;     // ORBs create ContextLists

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline CORBA_ContextList_ptr _duplicate(CORBA_ContextList_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline CORBA_ContextList_ptr _nil()
    { return 0; }

    CORBA_ULong count() const;
    
    void add(const char*);
    void add_consume(char*);

    const char* item(CORBA_ULong);

    CORBA_Status remove(CORBA_ULong);
};

inline void
CORBA_release(CORBA_ContextList_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(CORBA_ContextList_ptr p)
{
    return p == 0;
}

//
// The Request class
//
class CORBA_Request;
typedef CORBA_Request* CORBA_Request_ptr;
typedef CORBA_Request_ptr RequestRef;
void OBDuplicate(CORBA_Request_ptr);
void OBRelease(CORBA_Request_ptr);
typedef OBObjVar< CORBA_Request > CORBA_Request_var;

class CORBA_Request : public OBRefCount
{
    CORBA_Object_var target_;
    CORBA_String_var operation_;
    CORBA_NVList_var arguments_;
    CORBA_NamedValue_var result_;
    CORBA_Environment_var environment_;
    CORBA_ExceptionList_var exceptions_;
    CORBA_ContextList_var contexts_;
    CORBA_Context_var ctx_;
    CORBA_ULong reqId_;

    //
    // Hide copy-constructor and asignment operator
    //
    CORBA_Request(const CORBA_Request&);
    void operator=(const CORBA_Request&);

    //
    // Marshal into sequence for a request
    // Unmarshal from sequence from a reply
    //
    void marshal(OBBuffer&);
    void unmarshal(const OBBuffer&, CORBA_ULong, bool, bool);

protected:

    CORBA_Request(CORBA_Object_ptr, const char*, CORBA_NVList_ptr,
		CORBA_NamedValue_ptr, CORBA_ExceptionList_ptr,
		CORBA_ContextList_ptr);

    CORBA_Request(CORBA_Object_ptr, const char*, CORBA_NVList_ptr,
		CORBA_NamedValue_ptr);

    CORBA_Request(CORBA_Object_ptr, const char*);
    
    friend class CORBA_Object; // Objects may create Requests

public:

    //
    // Standard IDL to C++ Mapping
    //
    static inline CORBA_Request_ptr _duplicate(CORBA_Request_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline CORBA_Request_ptr _nil()
    { return 0; }

    CORBA_Object_ptr target() const;
    const char* operation() const;
    CORBA_NVList_ptr arguments();
    CORBA_NamedValue_ptr result();
    CORBA_Environment_ptr env();
    CORBA_ExceptionList_ptr exceptions();
    CORBA_ContextList_ptr contexts();

    void ctx(CORBA_Context_ptr);
    CORBA_Context_ptr ctx() const;

    CORBA_Any& add_in_arg();
    CORBA_Any& add_in_arg(const char*);
    CORBA_Any& add_inout_arg();
    CORBA_Any& add_inout_arg(const char*);
    CORBA_Any& add_out_arg();
    CORBA_Any& add_out_arg(const char*);
    void set_return_type(CORBA_TypeCode_ptr);
    CORBA_Any& return_value();

    CORBA_Status invoke();
    CORBA_Status send_oneway();
    CORBA_Status send_deferred();
    CORBA_Status get_response();
    CORBA_Boolean poll_response();
};

inline void
CORBA_release(CORBA_Request_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(CORBA_Request_ptr p)
{
    return p == 0;
}

//
// UnkownUserException defined here, since it belongs logically
// to the DII
//
class CORBA_UnknownUserException : public CORBA_UserException
{
    CORBA_Any any_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    CORBA_UnknownUserException() { }
    CORBA_UnknownUserException(const CORBA_UnknownUserException&);
    CORBA_UnknownUserException(const CORBA_Any&);
    CORBA_UnknownUserException& operator=(const CORBA_UnknownUserException&);

    CORBA_Any& exception() { return any_; }

    virtual void _raise() const { throw *this; }

    static CORBA_UnknownUserException* _narrow(CORBA_Exception*);

    //
    // Additional ORBacus specific functions
    //
    virtual const char* _type_id() const;

    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
#ifdef HAVE_NO_RTTI
    virtual void* _OB_narrowHelp(const char*) const;
#endif
    virtual CORBA_Exception* _OB_clone() const;
};

#endif
