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

#ifndef OB_INITIAL_SERVICE_MANAGER_H
#define OB_INITIAL_SERVICE_MANAGER_H

#include <OB/InitialServiceManager_fwd.h>

#include <OB/NativeTypes.h>
#include <OB/StubImpl.h> // For CORBA::Policy
#include <OB/MarshalStubImpl.h> // For CORBA::Policy
#include <OB/OBORB.h> // Needed for ORB::InvalidName
#include <OB/Hashtable.h>

namespace OB
{

//
// The InitialServiceManager class
//
class InitialServiceManager : public RefCount, public JTCRecursiveMutex
{
    //
    // Hide copy-constructor and assignment operator
    //
    InitialServiceManager(const InitialServiceManager&);
    void operator=(const InitialServiceManager&);

    //
    // Set of available initial services
    //
    struct Service
    {
        CORBA::String_var ref;
        CORBA::Object_var obj;

#if defined(__BORLANDC__)
	Service& operator=(const Service& rhs)
	{
	    if (this == &rhs)
		return *this;
	    ref = rhs.ref;
	    obj = rhs.obj;
	    return *this;
	}
#endif
    };

    typedef Hashtable<CORBA::String_var, Service, StringHasher> ServiceMap;
    ServiceMap* services_;

    CORBA::String_var defaultInitRef_;

    bool destroy_; // True if destroy() was called

    ORBInstance_var orbInstance_; // The ORBInstance object

public:

    InitialServiceManager();
    virtual ~InitialServiceManager();

    static inline InitialServiceManager_ptr
    _duplicate(InitialServiceManager_ptr p)
    { if(p) p -> _OB_incRef(); return p; }

    static inline InitialServiceManager_ptr _nil()
    { return 0; }

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

    //
    // Set the ORBInstance object. Note that the initial service map
    // isn't populated until this method is called.
    //
    void setORBInstance(ORBInstance_ptr);

    CORBA::ORB::ObjectIdList* listInitialServices()
	throw(CORBA::SystemException);

    CORBA::Object_ptr resolveInitialReferences(const char*)
	throw(CORBA::SystemException, CORBA::ORB::InvalidName);

    void addInitialReference(const char*, CORBA::Object_ptr)
	throw(CORBA::SystemException, CORBA::ORB::InvalidName);

    void addInitialReference(const char*, CORBA::Object_ptr, bool)
	throw(CORBA::SystemException, CORBA::ORB::InvalidName);

    void addInitialReference(const char*, const char*, bool)
	throw(CORBA::SystemException, CORBA::ORB::InvalidName);
};

} // End of namespace OB

namespace CORBA
{

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

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

} // End of namespace CORBA

#endif
