package com.ociweb.JavaAddLib;

import java.util.*;

import org.omg.CORBA.UserException;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;

// package scope if not given a modifier
public class Naming {

	static final NameComponent[] _adders = new NameComponent[] { new NameComponent("Adders", "") };
		
	public static void bind(org.omg.CORBA.ORB orb, Ref ref) throws UserException {
		// create "Adders" context - careful if it already exists 
		// register name under "Adders"
		NamingContext nsCtx = 
				NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));  // can throw InvalidName
		// could raise SystemException, too
		
        NamingContext addersCtx = null;
        try {
        	addersCtx = nsCtx.bind_new_context(_adders);  // NotFound, AlreadyBound, CannotProceed, InvalidName
		} catch (AlreadyBound e) {
			// ok - context already exists
			addersCtx = NamingContextHelper.narrow(nsCtx.resolve(_adders));
		}
        
        // System.out.println("Binding: " + ref.Name + " -> " + orb.object_to_string(ref.ObjRef));
        
        NameComponent[] name = {new NameComponent(ref.Name, "")}; 
        addersCtx.rebind(name, ref.ObjRef);
	}
	
	
	
	public static void unbind(org.omg.CORBA.ORB orb, Ref ref) throws UserException {
		NamingContext nsCtx = 
				NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));  // can throw InvalidName
	
		NamingContext addersCtx = 
				NamingContextHelper.narrow(nsCtx.resolve(_adders));
		
		NameComponent[] name = { new NameComponent(ref.Name, "") };
		addersCtx.unbind(name);
		
		// if the adder that was just removed was the last one, remove the context, too
		if (list(orb).isEmpty()) {
			addersCtx.destroy();  // H&V 689 - destroy the context, unbind the name from the parent
			nsCtx.unbind( _adders);
		}
	}
	
	
	static void addBindings(BindingListHolder blh, NamingContext addersCtx, Vector<Ref> refList) throws UserException {
	    Binding bindings[] = blh.value;
        for (int i=0; i<bindings.length; i++) {
        	org.omg.CORBA.Object objRef = addersCtx.resolve(bindings[i].binding_name);
        	String name = bindings[i].binding_name[bindings[i].binding_name.length -1].id; // last component of the name	
        	refList.add(new Ref(name, objRef));
        }
	}

	// see:  http://docs.oracle.com/javase/1.4.2/docs/guide/idl/tnameserv.html
	public static Vector<Ref> list(org.omg.CORBA.ORB orb) throws UserException {
		Vector<Ref> refList = new Vector<Ref>();
		
		NamingContext nsCtx = 
				NamingContextHelper.narrow(orb.resolve_initial_references("NameService"));  // can throw InvalidName

		NamingContext addersCtx;
		try {
			addersCtx = NamingContextHelper.narrow(nsCtx.resolve(_adders));
		} catch (NotFound e) {
			return refList;  // no context, so no adders
		}
		
		BindingListHolder blh = new BindingListHolder();
        BindingIteratorHolder bIth= new BindingIteratorHolder();
		int chunkSize=100;
        addersCtx.list(chunkSize, blh, bIth);
        
        // iterate over the list - H&V 697
		addBindings(blh, addersCtx, refList);
		if (bIth != null) {
			BindingIterator bi = bIth.value;
			while (bi.next_n(chunkSize, blh))
				addBindings(blh, addersCtx, refList);
			bi.destroy();
		}

		return refList;
	}
}
