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

#include <OB/Basic.h>
#include <OB/Except.h>
#include <OB/Template.h>
#include <OB/TemplateI.h>
#include <OB/Declarations.h>
#include <OB/Any.h>
#include <OB/IOP.h>
#include <OB/Object.h>
#include <OB/IntRep.h>
#include <OB/ORB.h>
#include <OB/Object_skel.h>
#include <OB/ImplRep.h>
#include <OB/BOA.h>

#include <stdio.h>

// ----------------------------------------------------------------------
// External, non-inline duplicate/release for templates
// ----------------------------------------------------------------------

void
OBDuplicate(OBServer_ptr p)
{
    OBServer::_duplicate(p);
}

void
OBRelease(OBServer_ptr p)
{
    CORBA_release(p);
}

// ----------------------------------------------------------------------
// Template instantiations
// ----------------------------------------------------------------------

#ifndef HAVE_NO_EXPLICIT_TEMPLATES
template class OBObjVar< OBServer >;
template class OBObjForSeq< OBServer >;
template class OBObjSeq< OBServer >;
template class OBSeqVar< OBObjSeq< OBServer > >;
#else
#ifdef HAVE_PRAGMA_DEFINE
#pragma define(OBObjVar< OBServer >)
#pragma define(OBObjForSeq< OBServer >)
#pragma define(OBObjSeq< OBServer >)
#pragma define(OBSeqVar< OBObjSeq<OBServer> >)
#endif
#endif

// ----------------------------------------------------------------------
// The Object skeleton public member implementation
// ----------------------------------------------------------------------

CORBA_BOA_ptr
CORBA_Object_skel::_boa()
{
    return CORBA_BOA::_OB_instance();
}

CORBA_ImplementationDef_ptr
CORBA_Object_skel::_get_implementation()
{
    return CORBA_ImplementationDef::_nil();
}

CORBA_InterfaceDef_ptr
CORBA_Object_skel::_get_interface()
{
    CORBA_Object_var obj;

    try
    {
	CORBA_ORB_ptr orb = CORBA_ORB::_OB_instance_nodup();
	if(CORBA_is_nil(orb))
	    throw CORBA_INITIALIZE("ORB not initialized");
	obj = orb -> resolve_initial_references("InterfaceRepository");
    }
    catch(const CORBA_ORB::InvalidName&)
    {
	throw CORBA_INTF_REPOS(OBMinorNoIntfRepos, CORBA_COMPLETED_NO);
    }

    if(CORBA_is_nil(obj))
    {
	throw CORBA_INTF_REPOS(OBMinorNoIntfRepos, CORBA_COMPLETED_NO);
    }
								       
    CORBA_Repository_var repository = CORBA_Repository::_narrow(obj);

    if(CORBA_is_nil(repository))
    {
	throw CORBA_INTF_REPOS(OBMinorNoIntfRepos, CORBA_COMPLETED_NO);
    }

    CORBA_Contained_var contained = repository -> lookup_id(_OB_typeId());
    if(CORBA_is_nil(contained))
	return CORBA_InterfaceDef::_nil();

    return CORBA_InterfaceDef::_narrow(contained);
}

CORBA_Boolean
CORBA_Object_skel::_non_existent()
{
    return false;
}

CORBA_Boolean
CORBA_Object_skel::_is_dynamic()
{
    return false;
}

OBDispatchStatus
CORBA_Object_skel::_OB_dispatch(const char* _ob_op,
				OBBuffer& _ob_buf,
				bool _ob_sw,
				CORBA_ULong _ob_offIn,
				CORBA_ULong _ob_offOut)
{
    //
    // Optimization. All operations that we dispatch start with an '_'
    // character.
    //
    if(*_ob_op != '_')
        return OBDispatchStatusNoOperation;
    
    static const char* names[] =
    {
        "_hash",
        "_implementation",
        "_interface",
        "_is_a",
        "_is_dynamic",
        "_is_equivalent",
        "_non_existent"
    };
    static const CORBA_ULong num = 7;

    switch(_OB_findOperation(_ob_op, names, num))
    {
    case 0: // _hash
    {
        const CORBA_Octet* _ob_co = _ob_buf.data + _ob_offIn;
        CORBA_ULong _ob_arg0;
        OBUnmarshal(_ob_arg0, _ob_co, _ob_sw);
	
        CORBA_ULong _ob_r = _hash(_ob_arg0);

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }
    
    case 1: // _implementation
    {
        CORBA_ImplementationDef_var _ob_r = _get_implementation();

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }

    case 2: // _interface
    {
        CORBA_InterfaceDef_var _ob_r = _get_interface();

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }

    case 3: // _is_a
    {
        const CORBA_Octet* _ob_co = _ob_buf.data + _ob_offIn;
        CORBA_String_var _ob_arg0;
        OBUnmarshal(_ob_arg0.inout(), _ob_co, _ob_sw);

        CORBA_Boolean _ob_r = _is_a(_ob_arg0);

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }
    
    case 4: // _is_dynamic  OB specific
    {
        CORBA_Boolean _ob_r = _is_dynamic();

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }
    
    case 5: // _is_equivalent
    {
        const CORBA_Octet* _ob_co = _ob_buf.data + _ob_offIn;
        CORBA_Object_var _ob_arg0;
        OBUnmarshal(_ob_arg0.inout(), _ob_co, _ob_sw);

        CORBA_Boolean _ob_r = _is_equivalent(_ob_arg0);

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }
    
    case 6: // _non_existent
    {
        CORBA_Boolean _ob_r = _non_existent();

	CORBA_ULong _ob_cnt = _ob_offOut;
	OBMarshalCount(_ob_r, _ob_cnt);
	
	_ob_buf.alloc(_ob_cnt);
	CORBA_Octet* _ob_o = _ob_buf.data + _ob_offOut;
	OBMarshal(_ob_r, _ob_o);
	
	return OBDispatchStatusOK;
    }
    }

    return OBDispatchStatusNoOperation;
}

CORBA_Long
CORBA_Object_skel::_OB_findOperation(const char* op,
                                     const char* names[],
                                     CORBA_ULong num)
{
    CORBA_Long l = 0;
    CORBA_Long r = (CORBA_Long)num;

    while(l < r)
    {
        CORBA_Long m = (l + r) / 2;
        int res = strcmp(names[m], op);
        if(res == 0)
            return m;
        else if(res > 0)
            r = m;
        else
            l = m + 1;
    }

    return -1;
}
