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

#ifndef OB_EXCEPT_H
#define OB_EXCEPT_H

//
// Undefine minor (this is needed for SunOS 4.1 and some other Unix flavors)
//
#undef minor

//
// The Exception classes
//
class CORBA_Exception
{
protected:

    CORBA_Exception() { }

public:

    //
    // Standard IDL to C++ Mapping
    //
    CORBA_Exception(const CORBA_Exception&) { }
    virtual ~CORBA_Exception() { }

    CORBA_Exception& operator=(const CORBA_Exception&) { return *this; }

    virtual void _raise() const = 0;

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

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

enum CORBA_CompletionStatus
{
    CORBA_COMPLETED_YES,
    CORBA_COMPLETED_NO,
    CORBA_COMPLETED_MAYBE
};

//
// When adding a new system exception ensure:
//
// Except.h
// OB_MAKE_STANDARD_EXCEPTION
// Except.cpp
// OB_MAKE_STANDARD_EXCEPTION_I
// OBUnmarshalSystemException, OBUnmarshalSystemExceptionThrow
//
// Any.h
// OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION
// Any.cpp
// OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION_I
//
// Typecode.h
// OB_IMPORT extern const OBTypeCodeSysExConst CORBA__tc_*;
// Typecode.cpp
// const OBTypeCodeSysExConst CORBA__tc_*("*");
// bool CORBA_TypeCode::_OB_isSystemException() const [add to]
//
// Util.cpp
// OBExceptionToString
//
// Update the Test suite
// Test2.idl
// add void op_*_Ex()
// TestDSI_impl
// Add new case for operation
// TestStubException
// Add new call for exception
// Test_impl
// Add new method
//
class CORBA_SystemException : public CORBA_Exception
{
    CORBA_String_var reason_; // ORBacus specific - not transmitted in
                              // remote method calls
    CORBA_ULong minor_;
    CORBA_CompletionStatus status_;

public:

    //
    // Standard IDL to C++ Mapping
    //
    CORBA_SystemException(const char* reason = "")
	: reason_(reason), minor_(0), status_(CORBA_COMPLETED_NO)
    {
    }

    CORBA_SystemException(CORBA_ULong minor, CORBA_CompletionStatus status)
	: reason_(CORBA_string_dup("")), minor_(minor), status_(status)
    {
    }

    CORBA_SystemException(const char* reason, CORBA_ULong minor,
			  CORBA_CompletionStatus status)
	: reason_(reason), minor_(minor), status_(status)
    {
    }

    CORBA_SystemException(const CORBA_SystemException& se)
	: reason_(se.reason_), minor_(se.minor_), status_(se.status_)
    {
    }

    CORBA_SystemException& operator=(const CORBA_SystemException& se)
    {
	if(this != &se)
	{
	    reason_ = se.reason_;
	    minor_ = se.minor_;
	    status_ = se.status_;
	}
	return *this;
    }

    CORBA_ULong minor() const { return minor_; }
    void minor(CORBA_ULong minor) { minor_ = minor; }
 
    CORBA_CompletionStatus completed() const { return status_; }
    void completed(CORBA_CompletionStatus status) { status_ = status; }

    static CORBA_SystemException* _narrow(CORBA_Exception*);

    //
    // Additional ORBacus specific functions
    //
    const char* reason() const { return reason_; }
    void reason(const char* reason) { reason_ = reason; }
    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
};

class CORBA_UserException : public CORBA_Exception
{
public:

    //
    // Standard IDL to C++ Mapping
    //
    CORBA_UserException() { }
    CORBA_UserException(const CORBA_UserException&) { }
    CORBA_UserException& operator=(const CORBA_UserException&)
    { return *this; }

    static CORBA_UserException* _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
};

/* UnknownUserException is in Any.h */

#ifdef HAVE_NO_RTTI

#define OB_MAKE_STANDARD_EXCEPTION(T) \
class CORBA_##T : public CORBA_SystemException \
{ \
public: \
 \
    CORBA_##T(const char* r = "") \
        : CORBA_SystemException(r) { } \
    CORBA_##T(CORBA_ULong m, CORBA_CompletionStatus s) \
        : CORBA_SystemException(m, s) { } \
    CORBA_##T(const char* r, CORBA_ULong m, CORBA_CompletionStatus s) \
        : CORBA_SystemException(r, m, s) { } \
    CORBA_##T(const CORBA_##T& ex) \
        : CORBA_SystemException(ex) { } \
\
    virtual void _raise() const { throw *this; } \
    static CORBA_##T* _narrow(CORBA_Exception*); \
    virtual const char* _type_id() const; \
    virtual void* _OB_narrowHelp(const char*) const; \
    virtual CORBA_Exception* _OB_clone() const; \
};

#else

#define OB_MAKE_STANDARD_EXCEPTION(T) \
class CORBA_##T : public CORBA_SystemException \
{ \
public: \
 \
    CORBA_##T(const char* r = "") \
        : CORBA_SystemException(r) { } \
    CORBA_##T(CORBA_ULong m, CORBA_CompletionStatus s) \
        : CORBA_SystemException(m, s) { } \
    CORBA_##T(const char* r, CORBA_ULong m, CORBA_CompletionStatus s) \
        : CORBA_SystemException(r, m, s) { } \
    CORBA_##T(const CORBA_##T& ex) \
        : CORBA_SystemException(ex) { } \
\
    virtual void _raise() const { throw *this; } \
    static CORBA_##T* _narrow(CORBA_Exception*); \
    virtual const char* _type_id() const; \
    virtual CORBA_Exception* _OB_clone() const; \
};

#endif

OB_MAKE_STANDARD_EXCEPTION(UNKNOWN)
OB_MAKE_STANDARD_EXCEPTION(BAD_PARAM)
OB_MAKE_STANDARD_EXCEPTION(NO_MEMORY)
OB_MAKE_STANDARD_EXCEPTION(IMP_LIMIT)
OB_MAKE_STANDARD_EXCEPTION(COMM_FAILURE)
OB_MAKE_STANDARD_EXCEPTION(INV_OBJREF)
OB_MAKE_STANDARD_EXCEPTION(NO_PERMISSION)
OB_MAKE_STANDARD_EXCEPTION(INTERNAL)
OB_MAKE_STANDARD_EXCEPTION(MARSHAL)
OB_MAKE_STANDARD_EXCEPTION(INITIALIZE)
OB_MAKE_STANDARD_EXCEPTION(NO_IMPLEMENT)
OB_MAKE_STANDARD_EXCEPTION(BAD_TYPECODE)
OB_MAKE_STANDARD_EXCEPTION(BAD_OPERATION)
OB_MAKE_STANDARD_EXCEPTION(NO_RESOURCES)
OB_MAKE_STANDARD_EXCEPTION(NO_RESPONSE)
OB_MAKE_STANDARD_EXCEPTION(PERSIST_STORE)
OB_MAKE_STANDARD_EXCEPTION(BAD_INV_ORDER)
OB_MAKE_STANDARD_EXCEPTION(TRANSIENT)
OB_MAKE_STANDARD_EXCEPTION(FREE_MEM)
OB_MAKE_STANDARD_EXCEPTION(INV_IDENT)
OB_MAKE_STANDARD_EXCEPTION(INV_FLAG)
OB_MAKE_STANDARD_EXCEPTION(INTF_REPOS)
OB_MAKE_STANDARD_EXCEPTION(BAD_CONTEXT)
OB_MAKE_STANDARD_EXCEPTION(OBJ_ADAPTER)
OB_MAKE_STANDARD_EXCEPTION(DATA_CONVERSION)
OB_MAKE_STANDARD_EXCEPTION(OBJECT_NOT_EXIST)
OB_MAKE_STANDARD_EXCEPTION(TRANSACTION_REQUIRED)
OB_MAKE_STANDARD_EXCEPTION(TRANSACTION_ROLLEDBACK)
OB_MAKE_STANDARD_EXCEPTION(INVALID_TRANSACTION)
OB_MAKE_STANDARD_EXCEPTION(INV_POLICY)

void OBMarshal(const CORBA_SystemException&, CORBA_Octet*&);
void OBMarshalCount(const CORBA_SystemException&, CORBA_ULong&);
CORBA_SystemException* OBUnmarshalSystemException(const CORBA_Octet*&, bool);
void OBUnmarshalSystemExceptionThrow(const CORBA_Octet*&, bool);

//
// Minor error codes for COMM_FAILURE
//
// Note: If something is changed here, it must also be changed in other
// ORBacus implementations, like ORBacus for Java.
//
enum OBMinorCommFailure
{
    OBMinorRecv = 1,           // recv() failed
    OBMinorSend,           // send() failed
    OBMinorRecvZero,       // recv() returned zero
    OBMinorSendZero,       // send() returned zero
    OBMinorSocket,         // socket() failed
    OBMinorSetsockopt,     // setsockopt() failed
    OBMinorGetsockopt,     // getsockopt() failed
    OBMinorBind,           // bind() failed
    OBMinorListen,         // listen() failed
    OBMinorConnect,        // connect() failed
    OBMinorAccept,         // accept() failed
    OBMinorSelect,         // select() failed

    OBMinorGethostname,    // gethostname() failed
    OBMinorGethostbyname,  // gethostbyname() failed

    OBMinorWSAStartup,     // WSAStartup() failed
    OBMinorWSACleanup,     // WSACleanup() failed

    OBMinorNoGIOP,         // Not a GIOP message
    OBMinorUnknownMessage, // Unknown GIOP message
    OBMinorWrongMessage,   // Wrong GIOP message
    OBMinorCloseConnection,// Got a close connection message
    OBMinorMessageError    // Got a message error message
};

//
// Minor error codes for INTF_REPOS
//
// Note: If something is changed here, it must also be changed in other
// ORBacus implementations, like ORBacus for Java.
//
enum OBMinorIntfRepos
{
    OBMinorNoIntfRepos = 1,       // Interface repository is not available
    OBMinorIdExists,              // Repository id already exists
    OBMinorNameExists,            // Name already exists
    OBMinorRepositoryDestroy,     // destroy() invoked on Repository object
    OBMinorPrimitiveDefDestroy,   // destroy() invoked on PrimitiveDef object
    OBMinorAttrExists,            // Attribute is already defined in a
                                  // base interface
    OBMinorOperExists,            // Operation is already defined in a
                                  // base interface
    OBMinorLookupAmbiguous,       // Search name for lookup() is ambiguous
    OBMinorAttrAmbiguous,         // Attribute name collisions in
                                  // base interfaces
    OBMinorOperAmbiguous,         // Operation name collisions in
                                  // base interfaces
    OBMinorIllegalRecursion,      // Illegal recursion
    OBMinorDupParameter		  // Duplicate declaration of formal param
};

enum OBMinorBadParam
{
    OBMinorBadSchemeName,         // Bad scheme name
    OBMinorBadAddress,            // Bad address
    OBMinorBadSchemeSpecificPart, // Bad scheme specific part
    OBMinorOther                  // Some other error
};

#endif
