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

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

#include <NamingExample.h>

void
PrintBinding(const CosNaming_Binding& b)
{
    CORBA_ULong i;

    for(i = 0 ; i < b.binding_name.length() ; i++)
    {
	if(i > 0)
	    cout << " ; ";
	
	cout << b.binding_name[i].id;
    }
    
    switch(b.binding_type)
    {
    case CosNaming_nobject:
	cout << " (object)" << endl;
	break;
	
    case CosNaming_ncontext:
	cout << " (context)" << endl;
	break;
    }
}

int
main(int argc, char* argv[], char*[])
{
    try
    {
	//
	// Create ORB
	//
	CORBA_ORB_var orb = CORBA_ORB_init(argc, argv);
	
	//
	// 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_NamingContext_var nc = CosNaming_NamingContext::_narrow(obj);

	if(CORBA_is_nil(nc))
	{
	    cerr << argv[0]
		 << ": `NameService' is not a NamingContext object reference"
		 << endl;
	    return 1;
	}

	//
	// Get objects by name
	//
	try
	{
	    CORBA_ULong i;

	    //
	    // Resolve names with the Naming Service
	    //
	    CosNaming_Name aName;
	    aName.length(1);
	    aName[0].id = CORBA_string_dup("a");
	    aName[0].kind = CORBA_string_dup("");
	    CORBA_Object_var aObj = nc -> resolve(aName);
	    Named_var a = Named::_narrow(aObj);
	    assert(!CORBA_is_nil(a));
	    cout << "Resolved `a'" << endl;

	    CosNaming_Name nc1Name;
	    nc1Name.length(1);
	    nc1Name[0].id = CORBA_string_dup("nc1");
	    nc1Name[0].kind = CORBA_string_dup("");
	    CORBA_Object_var nc1Obj = nc -> resolve(nc1Name);
	    CosNaming_NamingContext_var nc1 =
		CosNaming_NamingContext::_narrow(nc1Obj);
	    assert(!CORBA_is_nil(nc1));
	    cout << "Resolved `nc1'" << endl;

	    CosNaming_Name bName;
	    bName.length(2);
	    bName[0].id = CORBA_string_dup("nc1");
	    bName[0].kind = CORBA_string_dup("");
	    bName[1].id = CORBA_string_dup("b");
	    bName[1].kind = CORBA_string_dup("");
	    CORBA_Object_var bObj = nc -> resolve(bName);
	    Named_var b = Named::_narrow(bObj);
	    assert(!CORBA_is_nil(b));
	    cout << "Resolved `b' in naming context `nc1'" << endl;

	    CosNaming_Name nc2Name;
	    nc2Name.length(2);
	    nc2Name[0].id = CORBA_string_dup("nc1");
	    nc2Name[0].kind = CORBA_string_dup("");
	    nc2Name[1].id = CORBA_string_dup("nc2");
	    nc2Name[1].kind = CORBA_string_dup("");
	    CORBA_Object_var nc2Obj = nc -> resolve(nc2Name);
	    CosNaming_NamingContext_var nc2 =
		CosNaming_NamingContext::_narrow(nc2Obj);
	    assert(!CORBA_is_nil(nc2));
	    cout << "Resolved `nc2' in naming context `nc1'" << endl;

	    CosNaming_Name cName;
	    cName.length(3);
	    cName[0].id = CORBA_string_dup("nc1");
	    cName[0].kind = CORBA_string_dup("");
	    cName[1].id = CORBA_string_dup("nc2");
	    cName[1].kind = CORBA_string_dup("");
	    cName[2].id = CORBA_string_dup("c");
	    cName[2].kind = CORBA_string_dup("");
	    CORBA_Object_var cObj = nc -> resolve(cName);
	    Named_var c = Named::_narrow(cObj);
	    assert(!CORBA_is_nil(c));
	    cout << "Resolved `c' in naming context `nc2' in naming context `nc1'"
		 << endl;

	    cout << "Listing all bindings:" << endl;
	    CosNaming_BindingList_var bl;
	    CosNaming_BindingIterator_var bi;
	    nc -> list(999999, bl.out(), bi.out());
	    for(i = 0 ; i < bl -> length() ; i++)
		PrintBinding(bl[i]);
	    assert(CORBA_is_nil(bi));

	    cout << "Now listing only two bindings:" << endl;
	    CosNaming_BindingList_var bl2;
	    CosNaming_BindingIterator_var bi2;
	    nc -> list(2, bl2.out(), bi2.out());
	    for(i = 0 ; i < bl2 -> length() ; i++)
		PrintBinding(bl2[i]);
	    assert(!CORBA_is_nil(bi2));

	    cout << "Listing the rest with the binding iterator:" << endl;
	    CosNaming_BindingList_var bl3;
	    bi2 -> next_n(999999, bl3);
	    for(i = 0 ; i < bl3 -> length() ; i++)
		PrintBinding(bl3[i]);
	    bi2 -> destroy();
	}
	catch(const CosNaming_NamingContext::NotFound& ex)
	{
	    cerr << argv[0] << ": Got a `NotFound' exception (";
	    switch(ex.why)
	    {
	    case CosNaming_NamingContext::missing_node:
		cerr << "missing node";
		break;

	    case CosNaming_NamingContext::not_context:
		cerr << "not context";
		break;

	    case CosNaming_NamingContext::not_object:
		cerr << "not object";
		break;
	    }
	    cerr << ")" << endl;
	    return 1;
	}
	catch(const CosNaming_NamingContext::CannotProceed&)
	{
	    cerr << argv[0] << ": Got a `CannotProceed' exception" << endl;
	    return 1;
	}
	catch(const CosNaming_NamingContext::InvalidName&)
	{
	    cerr << argv[0] << ": Got an `InvalidName' exception" << endl;
	    return 1;
	}
	catch(const CosNaming_NamingContext::AlreadyBound&)
	{
	    cerr << argv[0] << ": Got an `AlreadyBound' exception" << endl;
	    return 1;
	}
	catch(const CosNaming_NamingContext::NotEmpty&)
	{
	    cerr << argv[0] << ": Got a `NotEmpty' exception" << endl;
	    return 1;
	}
    }
    catch(const CORBA_SystemException& ex)
    {
	OBPrintException(ex);
	return 1;
    }

    return 0;
}
