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

#ifndef OB_ANY_H
#define OB_ANY_H

#include <OB/Principal_fwd.h>
#include <OB/Object_fwd.h>
#include <OB/AbstractBase_fwd.h>
#include <OB/ValueBase_fwd.h>
#include <OB/ORBInstance_fwd.h>
#include <OB/TypeCode_fwd.h>
#include <OB/Stream_fwd.h>

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

namespace CORBA
{

//
// The Any class
//
class Any
{
    TypeCode_var type_;
    void* value_;
    Boolean rel_;
    const OB::ConstructedInfo* info_;
    OB::ORBInstance_var orbInstance_;

    //
    // Hide to catch erroneous attempts to insert or extract
    // to unsigned char or boolean
    //
    void operator<<=(unsigned char);
    Boolean operator>>=(unsigned char&) const;

    void operator<<=(bool);
    Boolean operator>>=(bool&) const;

public:

    Any();
    Any(const Any&);
    Any(TypeCode_ptr, void*, Boolean = false);
    ~Any();

    Any& operator=(const Any&);

    void operator<<=(Short);
    void operator<<=(UShort);
    void operator<<=(Long);
    void operator<<=(ULong);
    void operator<<=(LongLong);
    void operator<<=(ULongLong);
    void operator<<=(Float);
    void operator<<=(Double);
    void operator<<=(LongDouble);
    void operator<<=(const char*);
    void operator<<=(const CORBA::String_var&);
    void operator<<=(const OB::StrForSeq&);
    void operator<<=(const wchar_t*);
    void operator<<=(const CORBA::WString_var&);
    void operator<<=(const OB::WStrForSeq&);
    void operator<<=(const Any&);
    void operator<<=(Any*);
    void operator<<=(const Exception&);
    void operator<<=(Exception*);
    void operator<<=(TypeCode_ptr);
    void operator<<=(TypeCode_ptr*);
    void operator<<=(Principal_ptr);
    void operator<<=(Principal_ptr*);
    void operator<<=(Object_ptr);
    void operator<<=(Object_ptr*);

    Boolean operator>>=(Short&) const;
    Boolean operator>>=(UShort&) const;
    Boolean operator>>=(Long&) const;
    Boolean operator>>=(ULong&) const;
    Boolean operator>>=(LongLong&) const;
    Boolean operator>>=(ULongLong&) const;
    Boolean operator>>=(Float&) const;
    Boolean operator>>=(Double&) const;
    Boolean operator>>=(LongDouble&) const;
    Boolean operator>>=(const char*&) const;
    Boolean operator>>=(const wchar_t*&) const;
    Boolean operator>>=(const Any*&) const;
    Boolean operator>>=(const SystemException*&) const;
    Boolean operator>>=(TypeCode_ptr&) const;
    Boolean operator>>=(Principal_ptr&) const;
    Boolean operator>>=(Object_ptr&) const;
    
    //
    // Special types for boolean, octet, char, fixed insertion and extraction
    //
    struct from_boolean
    {
	Boolean val;

	from_boolean(Boolean v) : val(v) {}
	from_boolean(const from_boolean& v) : val(v.val) {}
    };

    struct from_octet
    {
	Octet val;

	from_octet(Octet v) : val(v) {}
	from_octet(const from_octet& v) : val(v.val) {}
    };

    struct from_char
    {
	Char val;

	from_char(Char v) : val(v) {}
	from_char(const from_char& v) : val(v.val) {}
    };

    struct from_wchar
    {
	WChar val;

	from_wchar(WChar v) : val(v) {}
	from_wchar(const from_wchar& v) : val(v.val) {}
    };

    struct from_string
    {
	char* val;
	ULong bound;
	Boolean nocopy;

	from_string(char* v, ULong b, Boolean nc = false)
	    : val(v), bound(b), nocopy(nc) {}
	from_string(const char* v, ULong b)
	    : val(const_cast<char*>(v)), bound(b), nocopy(false) {}
	from_string(const from_string& v)
	    : val(v.val), bound(v.bound), nocopy(v.nocopy) {}
    };
 
    struct from_wstring
    {
	wchar_t* val;
	ULong bound;
	Boolean nocopy;

	from_wstring(wchar_t* v, ULong b, Boolean nc = false)
	    : val(v), bound(b), nocopy(nc) {}
	from_wstring(const wchar_t* v, ULong b)
	    : val(const_cast<wchar_t*>(v)), bound(b), nocopy(false) {}
	from_wstring(const from_wstring& v)
	    : val(v.val), bound(v.bound), nocopy(v.nocopy) {}
    };

    struct from_fixed
    {
	const Fixed& val;
	UShort digits;
	UShort scale;

	from_fixed(const Fixed& f, UShort d, UShort s)
	    : val(f), digits(d), scale(s) {}
	from_fixed(const from_fixed& v) : val(v.val), digits(v.digits),
	    scale(v.scale) {}
    };

    void operator<<=(from_boolean);
    void operator<<=(from_octet);
    void operator<<=(from_char);
    void operator<<=(from_wchar);
    void operator<<=(from_string);
    void operator<<=(from_wstring);
    void operator<<=(from_fixed);

    struct to_boolean
    {
	Boolean& val;

	to_boolean(Boolean& v) : val(v) {}
	to_boolean(const to_boolean& v) : val(v.val) {}
    };

    struct to_octet
    {
	Octet& val;

	to_octet(Octet& v) : val(v) {}
	to_octet(const to_octet& v) : val(v.val) {}
    };

    struct to_char
    {
	Char& val;

	to_char(Char& v) : val(v) {}
	to_char(const to_char& v) : val(v.val) {}
    };

    struct to_wchar
    {
	WChar& val;

	to_wchar(WChar& v) : val(v) {}
	to_wchar(const to_wchar& v) : val(v.val) {}
    };

    struct to_string
    {
	const char*& val;
	ULong bound;

	to_string(const char*& v, ULong b) : val(v), bound(b) {}
	to_string(const to_string& v) : val(v.val), bound(v.bound) {}

        // Deprecated
	to_string(char*& v, ULong b) : val((const char*&)v), bound(b) {}
    };

    struct to_wstring
    {
	const wchar_t*& val;
	ULong bound;

	to_wstring(const wchar_t*& v, ULong b) : val(v), bound(b) {}
	to_wstring(const to_wstring& v) : val(v.val), bound(v.bound) {}

        // Deprecated
	to_wstring(wchar_t*& v, ULong b) : val((const wchar_t*&)v), bound(b) {}
    };

    struct to_fixed
    {
	Fixed& val;
	UShort digits;
	UShort scale;

	to_fixed(Fixed& f, UShort d, UShort s)
	    : val(f), digits(d), scale(s) {}
	to_fixed(const to_fixed& v) : val(v.val), digits(v.digits),
	    scale(v.scale) {}
    };

    struct to_object
    {
	Object_ptr& val;

	to_object(Object_out v) : val(v.ptr()) {}
	to_object(const to_object& v) : val(v.val) {}
    };

    struct to_abstract_base
    {
        AbstractBase_ptr& val;

        to_abstract_base(AbstractBase_ptr& v) : val(v) {}
        to_abstract_base(const to_abstract_base& v) : val(v.val) {}
    };

    struct to_value
    {
        ValueBase*& val;

        to_value(ValueBase*& v) : val(v) {}
        to_value(const to_value& v) : val(v.val) {}
    };

    Boolean operator>>=(to_boolean) const;
    Boolean operator>>=(to_octet) const;
    Boolean operator>>=(to_char) const;
    Boolean operator>>=(to_wchar) const;
    Boolean operator>>=(to_string) const;
    Boolean operator>>=(to_wstring) const;
    Boolean operator>>=(to_fixed) const;
    Boolean operator>>=(to_object) const;
    Boolean operator>>=(to_abstract_base) const;
    Boolean operator>>=(to_value) const;

    void replace(TypeCode_ptr, void*, Boolean = false);
    TypeCode_ptr type() const;
    void type(TypeCode_ptr);
    const void* value() const;

    //
    // Additional ORBacus functions
    //
    void replace(TypeCode_ptr, void*, Boolean, const OB::ConstructedInfo*);
    Boolean check_type(TypeCode_ptr) const;
    const OB::ConstructedInfo* info() const { return info_; }
    OB::InputStream_ptr create_input_stream() const;

    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
    void _OB_ORBInstance(OB::ORBInstance_ptr);
    OB::ORBInstance_ptr _OB_ORBInstance();

    TypeCode_ptr _OB_type_nodup() const;

    //
    // CDR
    //
    friend class ::OB::InputStreamImpl;
    friend class ::OB::OutputStreamImpl;
};

//
// Create variable type
//
typedef OB::VarVar< Any > Any_var;
typedef OB::VarOut< Any > Any_out;

} // End of namespace CORBA

//
// Insertion and extraction on Any_var
//
void operator<<=(CORBA::Any_var&, CORBA::Short);
void operator<<=(CORBA::Any_var&, CORBA::UShort);
void operator<<=(CORBA::Any_var&, CORBA::Long);
void operator<<=(CORBA::Any_var&, CORBA::ULong);
void operator<<=(CORBA::Any_var&, CORBA::LongLong);
void operator<<=(CORBA::Any_var&, CORBA::ULongLong);
void operator<<=(CORBA::Any_var&, CORBA::Float);
void operator<<=(CORBA::Any_var&, CORBA::Double);
void operator<<=(CORBA::Any_var&, CORBA::LongDouble);
void operator<<=(CORBA::Any_var&, const char*);
void operator<<=(CORBA::Any_var&, char*);
void operator<<=(CORBA::Any_var&, const CORBA::String_var&);
void operator<<=(CORBA::Any_var&, const OB::StrForSeq&);
void operator<<=(CORBA::Any_var&, const wchar_t*);
void operator<<=(CORBA::Any_var&, wchar_t*);
void operator<<=(CORBA::Any_var&, const CORBA::WString_var&);
void operator<<=(CORBA::Any_var&, const OB::WStrForSeq&);
void operator<<=(CORBA::Any_var&, const CORBA::Any&);
void operator<<=(CORBA::Any_var&, CORBA::Any*);
void operator<<=(CORBA::Any_var&, CORBA::TypeCode_ptr);
void operator<<=(CORBA::Any_var&, CORBA::TypeCode_ptr*);
void operator<<=(CORBA::Any_var&, CORBA::Principal_ptr);
void operator<<=(CORBA::Any_var&, CORBA::Principal_ptr*);
void operator<<=(CORBA::Any_var&, CORBA::Object_ptr);
void operator<<=(CORBA::Any_var&, CORBA::Object_ptr*);

CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Short&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::UShort&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Long&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::ULong&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::LongLong&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::ULongLong&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Float&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Double&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::LongDouble&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, const char*&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, const wchar_t*&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, const CORBA::Any*&);
CORBA::Boolean operator>>=(const CORBA::Any_var&,
			   const CORBA::SystemException*&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::TypeCode_ptr&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Principal_ptr&);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Object_ptr&);

void operator<<=(CORBA::Any_var&, CORBA::Any::from_boolean);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_octet);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_char);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_wchar);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_string);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_wstring);
void operator<<=(CORBA::Any_var&, CORBA::Any::from_fixed);

CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_boolean);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_octet);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_char);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_wchar);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_string);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_wstring);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_fixed);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_object);
CORBA::Boolean operator>>=(const CORBA::Any_var&,
			   CORBA::Any::to_abstract_base);
CORBA::Boolean operator>>=(const CORBA::Any_var&, CORBA::Any::to_value);

//
// Insertion and extraction for system exceptions
//
#define OB_MAKE_STANDARD_EXCEPTION_INSERTION_EXTRACTION(T) \
namespace CORBA \
{ \
class T; \
} \
void operator<<=(CORBA::Any&, CORBA::T*); \
void operator<<=(CORBA::Any&, const CORBA::T&); \
CORBA::Boolean operator>>=(const CORBA::Any&, const CORBA::T*&); \
inline void \
operator<<=(CORBA::Any_var& a, CORBA::T* v) \
{ a.inout() <<= v; } \
inline void \
operator<<=(CORBA::Any_var& a, const CORBA::T& v) \
{ a.inout() <<= v; } \
inline CORBA::Boolean \
operator>>=(const CORBA::Any_var& a, const CORBA::T*& v) \
{ return a.in() >>= v; }

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

#endif
