package jacorb.orb.portableInterceptor;

import org.omg.PortableInterceptor.*;
import java.util.*;
/**
 * This class "manages" the portable interceptors registered
 * with the ORB, and controls the PICurrent.
 *
 * @author Nicolas Noffke
 * @version $Id: InterceptorManager.java,v 1.1 2000/03/30 12:20:40 noffke Exp $
 */

public class InterceptorManager  {
  private ClientRequestInterceptor[] client_req_interceptors = null;
  private ServerRequestInterceptor[] server_req_interceptors = null;

  private PICurrentImpl client_current = null;
  private Hashtable server_currents = null;
  private org.omg.CORBA.ORB orb = null;
  private int current_slots = 0;

  public static final PICurrentImpl EMPTY_CURRENT = new PICurrentImpl(null, 0);

  public InterceptorManager(Vector client_interceptors,
			    Vector server_interceptors,
			    int slot_count,
			    org.omg.CORBA.ORB orb) {

    jacorb.util.Debug.output(2, "InterceptorManager started with " + 
			     server_interceptors.size() +" SIs and " 
			     + client_interceptors.size() + " CIs ");

    //build sorted arrays of interceptors
    client_req_interceptors = new ClientRequestInterceptor
      [client_interceptors.size()];

    //selection sort
    for (int j = 0; j < client_req_interceptors.length; j++){
      String min = ((ClientRequestInterceptor) client_interceptors.elementAt(0)).
	name();
      int min_index = 0;

      for(int _i = 1; _i < client_interceptors.size(); _i++)
	if (min.compareTo(((ClientRequestInterceptor) client_interceptors.
			   elementAt(_i)).name()) > 0){
	  min = ((ClientRequestInterceptor) client_interceptors.elementAt(_i)).
	    name();
	  min_index = _i;
	}

      client_req_interceptors[j] = (ClientRequestInterceptor) 
	client_interceptors.elementAt(min_index);
      client_interceptors.removeElementAt(min_index);
    }

    server_req_interceptors = new ServerRequestInterceptor
      [server_interceptors.size()];
   //selection sort
    for (int j = 0; j < server_req_interceptors.length; j++){
      String min = ((ServerRequestInterceptor) server_interceptors.elementAt(0)).
	name();
      int min_index = 0;

      for(int _i = 1; _i < server_interceptors.size(); _i++)
	if (min.compareTo(((ServerRequestInterceptor) server_interceptors.
			   elementAt(_i)).name()) > 0){
	  min = ((ServerRequestInterceptor) server_interceptors.elementAt(_i)).
	    name();
	  min_index = _i;
	}

      server_req_interceptors[j] = (ServerRequestInterceptor) 
	server_interceptors.elementAt(min_index);
      server_interceptors.removeElementAt(min_index);   
    }

    this.orb = orb;
    current_slots = slot_count;

    client_current = new PICurrentImpl(orb, current_slots);
    server_currents = new Hashtable();
  }

  /**
   * This method returns a PICurrent. If a server side current (i.e.
   * one associated with a Thread) is available then that is returned,
   * otherwise a client side current (i.e. one, that is not associated 
   * with a specific thread).
   */
  public Current getCurrent(){
    Current ts_current = (Current) server_currents.get(Thread.currentThread());
    
    if (ts_current != null)
      return ts_current;
    else
      return client_current;
  }

  /**
   * Sets the thread scope current, i.e. a server side current
   * associated with the calling  thread.
   */
  public void setTSCurrent(Current current){
    server_currents.put(Thread.currentThread(), 
			new PICurrentImpl((PICurrentImpl)current));
  }

  /**
   * Removes the thread scope current, that is associated with the
   * calling thread.
   */
  public void removeTSCurrent(){
    server_currents.remove(Thread.currentThread());
  }

  /**
   * Returns an empty current where no slot has been set.
   */
  public Current getEmptyCurrent(){
    return new PICurrentImpl(orb, current_slots);
  }

  /**
   * Returns an iterator object that contains the ClientRequestInterceptors
   * of this manager.
   *
   * @param forward if set to true, the interceptors will be invoked in 
   * ascending order, and it is possible to reverse the direction for one 
   * time. <br>
   * If set to false, the interceptors are invoked in descending order and 
   * reversing is not possible.
   */
  public ClientInterceptorEnumeration getClientEnumeration(boolean forward){
    return new ClientInterceptorEnumeration(client_req_interceptors, forward);
  }

  /**
   * Returns an iterator object that contains the ServerRequestInterceptors
   * of this manager.
   *
   * @param forward if set to true, the interceptors will be invoked in 
   * ascending order, and it is possible to reverse the direction for one 
   * time. <br>
   * If set to false, the interceptors are invoked in descending order and 
   * reversing is not possible.
   */
  public ServerInterceptorEnumeration getServerEnumeration(boolean forward){
    return new ServerInterceptorEnumeration(server_req_interceptors, forward);
  }
  
  /**
   * Test, if the manager has ClientRequestInterceptors
   */
  public boolean hasClientRequestInterceptors(){
    return client_req_interceptors.length > 0;
  }

  /**
   * Test, if the manager has ServerRequestInterceptors
   */
  public boolean hasServerRequestInterceptors(){
    return server_req_interceptors.length > 0;
  }

} // InterceptorManager
