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

#ifndef OB_OB_OBJECT_H
#define OB_OB_OBJECT_H

#include <OB/Object.h>
#include <OB/OBObject_fwd.h>
#include <OB/StubImpl_fwd.h>
#include <OB/MarshalStubImpl_fwd.h>
#include <OB/ORBInstance_fwd.h>
#include <OB/RefCounted_fwd.h>

#include <OB/Any.h>
#include <OB/TypeCodeConst.h>

namespace OBCORBA
{

//
// The Object class
//
class Object : virtual public CORBA::Object, virtual public OB::RefCount
{
    //
    // Hide copy-constructor and assignment operator
    //
    Object(const Object&);
    void operator=(const Object&);

    //
    // Mutex for CORBA::Object members. Deriving from a mutex would be
    // to intrusive, as locality-constrained classes derive directly
    // from this class, and thus would inherit this mutex as well.
    //
    JTCMutex mutex_;

    //
    // The ORBInstance object
    //
    OB::ORBInstance_var orbInstance_;
    
    //
    // The IOR and the original IOR
    //
    OB::RefCountIOR_var IOR_;
    OB::RefCountIOR_var origIOR_;

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

    //
    // The stub implementation
    //
    OB::StubImplBase_var stubImpl_;

    //
    // Check whether it's safe to retry
    //
    void _OB_checkRetry(CORBA::ULong, const CORBA::SystemException&);

protected:

    //
    // Management operations for the stub implementation
    //
    OB::StubImplBase_ptr _OB_getStubImpl();
    OB::MarshalStubImpl_ptr _OB_getMarshalStubImpl();

    //
    // Create a new marshal stub implementation. Derived stubs
    // overwrite this method to return a more derived marshal stub
    // implementation.
    //
    virtual OB::MarshalStubImpl_ptr _OB_createMarshalStubImpl();

    //
    // Constructor is protected
    //
    Object();

    //
    // OB::ObjectFactory may create OBCORBA::Objects
    //
    friend class ::OB::ObjectFactory;

    //
    // The DII needs access to _OB_getMarshalStubImpl()
    //
    friend class ::CORBA::Request;

public:

    virtual ~Object();

    static inline Object_ptr _duplicate(Object_ptr p)
	{ if(p) p -> _add_ref(); return p; }
    static inline Object_ptr _nil()
	{ return 0; }

    static Object_ptr _narrow(CORBA::Object_ptr);
    static Object_ptr _narrow(CORBA::AbstractBase_ptr);

    virtual CORBA::InterfaceDef_ptr _get_interface();
    virtual CORBA::Boolean _is_a(const char*);
    virtual CORBA::Boolean _non_existent();

    virtual CORBA::Boolean _is_equivalent(CORBA::Object_ptr);
    virtual CORBA::ULong _hash(CORBA::ULong);

    virtual void _create_request(CORBA::Context_ptr, const char*,
				 CORBA::NVList_ptr, CORBA::NamedValue_ptr,
				 CORBA::Request_out, CORBA::Flags);

    virtual void _create_request(CORBA::Context_ptr, const char*,
				 CORBA::NVList_ptr,
				 CORBA::NamedValue_ptr,
				 CORBA::ExceptionList_ptr,
				 CORBA::ContextList_ptr,
				 CORBA::Request_out,
				 CORBA::Flags);

    virtual CORBA::Request_ptr _request(const char*);

    virtual CORBA::Policy_ptr _get_policy(CORBA::PolicyType);
    virtual CORBA::Object_ptr _set_policy_overrides(
	const CORBA::PolicyList&, CORBA::SetOverrideType);
	//throw(SystemException, InvalidPolicies);
    
    //
    // Policies
    // From draft messaging specification
    //
    virtual CORBA::PolicyList* _get_policy_overrides(
	const CORBA::PolicyTypeSeq&);
    virtual CORBA::Policy_ptr _get_client_policy(CORBA::PolicyType);
    virtual CORBA::Boolean _validate_connection(CORBA::PolicyList_out);

    //
    // Additional ORBacus-specific functions
    //
    virtual OCI::ConnectorInfo_ptr _get_oci_connector_info();
    virtual OCI::TransportInfo_ptr _get_oci_transport_info();

    //
    // Implements OB::RefCountable
    //
    virtual void _add_ref();
    virtual void _remove_ref();

    //
    // ORBacus internal functions
    // Application programs must not use these functions directly
    //
    virtual const char** _OB_ids() const;

    void _OB_setup(OB::ORBInstance_ptr, OB::RefCountIOR_ptr,
		   OB::RefCountPolicyList_ptr);
    void _OB_copyFrom(CORBA::Object_ptr);

    OB::ORBInstance_ptr _OB_ORBInstance() const;

    virtual OB::RefCountIOR_ptr _OB_IOR() const;
    virtual OB::RefCountIOR_ptr _OB_origIOR() const;

    virtual void _OB_marshalOrigIOR(OB::OutputStreamImpl*) const;

    OB::RefCountPolicyList_ptr _OB_policies() const;
    CORBA::Policy_ptr _OB_getPolicy(CORBA::PolicyType) const;
    
    void _OB_handleException(const OB::ExceptionBase&, CORBA::ULong&,
                             CORBA::ULong&, bool = false);

    virtual CORBA::AbstractBase_ptr _OB_toAbstractBase();

    friend class OB::InputStream;
    friend class OB::OutputStream;
};

} // End of namespace OBCORBA

namespace OBCORBA
{

class ORB_impl; // For the friend declaration

} // End of namespace CORBA

namespace OB
{
    
//
// The ObjectFactory class
//
class ObjectFactory : public RefCount
{
    //
    // Hide copy-constructor and assignment operator
    //
    ObjectFactory(const ObjectFactory&);
    void operator=(const ObjectFactory&);

    bool destroy_; // True if destroy() was called
    ORBInstance_var orbInstance_; // The ORBInstance object
    CORBA::PolicyManager_var policyManager_; // The PolicyManager object

    ObjectFactory();
    ~ObjectFactory();
    friend class ::OBCORBA::ORB_impl; // ORB_impl creates ObjectFactory

public:

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

    //
    // Destroy the ObjectFactory
    //
    void destroy();

    //
    // Set the ORBInstance object
    //
    void setORBInstance(ORBInstance_ptr);

    //
    // Set the PolicyManager object
    //
    void setPolicyManager(CORBA::PolicyManager_ptr);

    //
    // Create a new CORBA::Object
    //
    CORBA::Object_ptr createObject(OB::RefCountIOR_ptr);

    //
    // Convert an IOR or URL to an object reference
    //
    CORBA::Object_ptr stringToObject(const char*);

    //
    // Get the list of policies new objects are created with
    //
    OB::RefCountPolicyList_ptr policies();
};

} // End of namespace OB

namespace CORBA
{

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

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

} // End of namespace CORBA


#endif
