package respool;

import java.util.*;
import java.io.*;

/**
 * Title: ResourcePool
 * Description: Maintains the pool of any objects like Threads, Database Connections etc.
 * Copyright:    Copyright (c) 2001
 * Company: Network Programs Ltd
 * @author N.PhanindraKumar
 * @version 1.0
 */

public class ResourcePool {

        /**
         * private member ResourceArray is to hold the objects to be pooled.
         */
        private Object[] ResourceArray = null;

        /**
         * private member BusyFlag holds the availability status of the pooled resources.
         */
        private boolean[] BusyFlag =null;

        /**
         * private member NumberofPoooledObjects holds the number of resources pooled.
         */
        private int NumberofPoooledObjects  = 1;

        /**
         * private member blocking indicates if the requests for resources are blocking calls or not.
         */
        private boolean blocking = true;


      /**
       * Contructor
       * @Param: ResourceObjects of type Collection with the resource objects to be pooled.
       */
      public ResourcePool(Collection ResourceObjects) {
           ResourceArray = ResourceObjects.toArray();
           this.NumberofPoooledObjects = ResourceObjects.size();

           BusyFlag = new boolean[ this.NumberofPoooledObjects ];
           for(int i=0; i<this.NumberofPoooledObjects; ++i) {
                 BusyFlag[i] = false;
           }
       }


      /**
       * Contructor
       * @Param: ResourceObjects of type Object[] with the resource objects to be pooled.
       */
      public ResourcePool(Object[] ResourceObjects)  {
           ResourceArray = ResourceObjects;
           this.NumberofPoooledObjects = ResourceObjects.length;

           BusyFlag = new boolean[ this.NumberofPoooledObjects ];
           for(int i=0; i<this.NumberofPoooledObjects; ++i) {
                 BusyFlag[i] = false;
           }
      }


      /**
       * synchronized Method: getFreeResource() - If the pooled object is not available when
       * the blocking flag is true, the thread will wait till a pooled object gets free for use.
       * If the pooled object is not available when the blocking flag is true, the method will
       * return "null" immediatly. If any pooled object is available then the object will be
       * returned declaring that the object is busy/occupied.
       *
       * @Param  : None
       * @return : Object
       * @throws : Exception
       */
      synchronized public Object getFreeResource() throws Exception {
           while(true){
                for(int i=0; i < NumberofPoooledObjects; ++i) {
                    if(BusyFlag[i] == false) {
                        BusyFlag[i] = true;
                        return(ResourceArray[i]);
                    }
                }
                if(this.blocking == true) {
                    wait();
                }
                else {
                    return( null );
                }
           }
      }


      /**
       * synchronized Method: releaseResource() - This method brings back the resource
       * object into the pool. It declares that the object is available for use.
       * It returns a boolean value TRUE if it could release the resource object
       * or else returns false or throws an exception.
       *
       * @Param  : Object - resource object to be realesed.
       * @return : boolean
       * @throws : Exception
       */
      synchronized public boolean releaseResource(Object Resource) throws Exception {
            for(int i=0; i < NumberofPoooledObjects; ++i) {
                if(ResourceArray[i] == Resource)  {
                    BusyFlag[i] = false;
                    notifyAll();
                    return(true);
                }
            }
            return(false);
      }


      /**
       * setBlocking() - Sets if the next calls for getFreeResource() are blocking
       * or not. If this method is invoked with "true" as the parameter, the next
       * call to the method getFreeResource() will retrieve the pooled object even
       * by waiting till it gets free. If this method is invoked with "false" as
       * the parameter, the next call to the method getFreeResource() will return
       * the pooled object if it is free or else returns "null" immediatly.
       *
       * @Param  : boolean - that determines if the getFreeResource() is blocking or not.
       * @return : boolean - that shows if the next call to getFreeResource() is blocking or not.
        */
      public boolean setBlocking(boolean isBlocking) {
          this.blocking = isBlocking;
          return(this.blocking);
      }

      /**
       * getBlocking() - tells if the next calls for getFreeResource() are blocking
       * calls or not.
       *
       * @return : boolean - that shows if the next call to getFreeResource() is blocking or not.
       */
      public boolean getBlocking() {
          return(this.blocking);
      }


}
