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

#include <assert.h>
#include <stdlib.h>
#include <string.h>

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

#include <OB/CosNaming.h>

#ifdef HAVE_IOSTREAM
#   include <iostream>
#else
#   include <iostream.h>
#endif


void TestBind(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestRebind(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestBindContext(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestRebindContext(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestResolve(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestUnbind(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestDestroy(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestList(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestListExtended(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestRename(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestCallbacks(CORBA_ORB_ptr orb, CosNaming_NamingContext_ptr root);
void TestToString(CORBA_ORB_ptr, CosNaming_NamingContextExt_ptr);
void TestToName(CORBA_ORB_ptr, CosNaming_NamingContextExt_ptr);
void TestToURL(CORBA_ORB_ptr, CosNaming_NamingContextExt_ptr);
void TestResolveStr(CORBA_ORB_ptr, CosNaming_NamingContextExt_ptr);

int
main(int argc, char* argv[], char*[])
{
    try
    {
	//
	// Create ORB and BOA
	//
	CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
	CORBA_BOA_var boa = orb -> BOA_init(argc, argv);
	boa -> init_servers();
	
	//
	// Get naming service
	//
	CORBA_Object_var obj;
	
	try
	{
	    obj = orb -> resolve_initial_references("NameService");
	}
	catch(const CORBA_ORB::InvalidName&)
	{
	    cerr << argv[0] << ": can't resolve `NameService'" << endl;
	    return 1;
	}
	
	if(CORBA_is_nil(obj))
	{
	    cerr << argv[0] << ": `NameService' is a nil object reference"
		 << endl;
	    return 1;
	}
	
	CosNaming_NamingContextExt_var nc =
	    CosNaming_NamingContextExt::_narrow(obj);
	
	if(CORBA_is_nil(nc))
	{
	    cerr << argv[0]
		 << ": `NameService' is not a NamingContextExt object "
		 << "reference" << endl;
	    return 1;
	}

	if(argc > 1)
	{
	    cout << "using: " << argv[1] << " as root context." << endl;
	    try
	    {
		CosNaming_Name_var name = nc -> to_name(argv[1]);
		obj = nc -> resolve(name);
	    }
	    catch(CORBA_UserException&)
	    {
		cerr << "Error resolving context." << endl;
		return 1;
	    }
	    nc = CosNaming_NamingContextExt::_narrow(obj);
	    assert(!CORBA_is_nil(nc));
	}

	try
	{
	    cout << "Testing bind()... " << flush;
	    TestBind(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing rebind()... " << flush;
	    TestRebind(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing bind_context()... " << flush;
	    TestBindContext(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing rebind_context()... " << flush;
	    TestRebindContext(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing resolve()... " << flush;
	    TestResolve(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing unbind()... " << flush;
	    TestUnbind(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing destroy()... " << flush;
	    TestDestroy(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing list()... " << flush;
	    TestList(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing list_extended()... " << flush;
	    TestListExtended(orb, nc);
	    cout << "OK!" << endl;
	    
	    cout << "Testing rename()... " << flush;
	    TestRename(orb, nc);
	    cout << "OK!" << endl;
	    
	    if(orb -> conc_model() == CORBA_ORB::ConcModelReactive)
	    {
		cout << "Testing callbacks... " << flush;
		TestCallbacks(orb, nc);
		cout << "OK!" << endl;
	    }
	    else
		cout << "** Cannot test callbacks unless -ORBreactive is used"
		     << endl;

            cout << "Testing to_string()... " << flush;
            TestToString(orb, nc);
            cout << "OK!" << endl;

            cout << "Testing to_name()... " << flush;
            TestToName(orb, nc);
            cout << "OK!" << endl;

            cout << "Testing to_url()... " << flush;
            TestToURL(orb, nc);
            cout << "OK!" << endl;

            cout << "Testing resolve_str()... " << flush;
            TestResolveStr(orb, nc);
            cout << "OK!" << endl;
	}
	catch(const CORBA_UserException&)
	{
	    cerr << argv[0] << ": Unexpected user exception was thrown"
		 << endl;
	    return 1;
	}
    }
    catch(const CORBA_SystemException& ex)
    {
	OBPrintException(ex);
	return 1;
    }

    return 0;
}
