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

#include <OB/CORBA.h>
#include <OB/Util.h>
#include <OB/Properties.h>

#include <OB/CosTypedEventChannelAdmin_skel.h>

#include <ProxyConsumer_impl.h>
#include <ProxyState.h>
#include <PropagatorBaseThread.h> // SGI 7.0/7.1 needs this, and PusherBase...
#include <PusherBaseThread.h>
#include <TEC_TypedProxyPushConsumer_impl.h>
#include <TEC_TypedSupplierAdmin_impl.h>
#include <TEC_TypedEventChannel_impl.h>

// ----------------------------------------------------------------------
// TEC_TypedSupplierAdmin_impl constructor and destructor
// ----------------------------------------------------------------------

TEC_TypedSupplierAdmin_impl::TEC_TypedSupplierAdmin_impl(
    CORBA_ORB_ptr orb,
    TEC_TypedEventChannel_impl* e)
    : orb_(CORBA_ORB::_duplicate(orb)),
      channel_(e),
      nextId_(0),
      destroyed_(false)
{
}

TEC_TypedSupplierAdmin_impl::~TEC_TypedSupplierAdmin_impl()
{
#ifdef OB_TRACE
    OBMessageViewer::instance() -> trace(2, "Destroy TypedSupplierAdmin");
#endif

}

// ----------------------------------------------------------------------
// TEC_TypedSupplierAdmin_impl public member implementation
// ----------------------------------------------------------------------

CosEventChannelAdmin_ProxyPushConsumer_ptr
TEC_TypedSupplierAdmin_impl::obtain_push_consumer()
{
    throw CORBA_NO_IMPLEMENT();
    return CosEventChannelAdmin_ProxyPushConsumer::_nil();
}

CosEventChannelAdmin_ProxyPullConsumer_ptr
TEC_TypedSupplierAdmin_impl::obtain_pull_consumer()
{
    throw CORBA_NO_IMPLEMENT();
    return CosEventChannelAdmin_ProxyPullConsumer::_nil();
}

CosTypedEventChannelAdmin_TypedProxyPushConsumer_ptr
TEC_TypedSupplierAdmin_impl::obtain_typed_push_consumer(const char* typeId)
{
    JTCSynchronized sync(*this);

    if(destroyed_)
        throw CORBA_OBJECT_NOT_EXIST();

    //
    // Attempt to assign this type id to the channel.
    //
    if(!channel_ -> assignTypeId(typeId))
	throw CosTypedEventChannelAdmin_InterfaceNotSupported();

    TEC_TypedProxyPushConsumer_impl* p =
        new TEC_TypedProxyPushConsumer_impl(orb_, channel_, this,
                                            channel_ -> getIface(),
                                            nextId_++);
    proxies_.append(p);

    return CosTypedEventChannelAdmin_TypedProxyPushConsumer::_duplicate(p);
}

CosEventChannelAdmin_ProxyPullConsumer_ptr
TEC_TypedSupplierAdmin_impl::obtain_typed_pull_consumer(const char*)
{
    throw CORBA_NO_IMPLEMENT();
    return CosEventChannelAdmin_ProxyPullConsumer::_nil();
}

void
TEC_TypedSupplierAdmin_impl::removeProxy(ProxyConsumer_impl* p)
{
    JTCSynchronized sync(*this);

    //
    // Find the element, remove it from the sequence.
    //
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
        if(proxies_[i] == p)
        {
            p -> release();
            proxies_.remove(i);
            return;
        }
    assert(false);
}

void
TEC_TypedSupplierAdmin_impl::disconnect()
{
    JTCSynchronized sync(*this);
    
    assert(!destroyed_);
    destroyed_ = true;

    //
    // disconnect each proxy.
    //
    for(CORBA_ULong i = 0; i < proxies_.length(); ++i)
    {
        proxies_[i] -> disconnect();
        proxies_[i] -> release();
    }
    proxies_.length(0);

    //
    // Disconnect the servant from the ORB.
    //
    orb_ -> disconnect(this);
}
