// file: $isip/class/search/ContextPool/cpol_05.cc
// version: $Id: cpol_05.cc 9000 2003-01-23 20:00:34Z alphonso $
//

// isip include files
//
#include "ContextPool.h"

// method: assign
//
// arguments:
//  const ContextPool& copy_node: (input) node to copy
//
// return: logical error status
//
// assign ContextPool from the copy
//
boolean ContextPool::assign(const ContextPool& copy_node_a) {

  // clear the contents
  //
  clear();
  
  // set the allocation mode
  //
  return pool_d.assign(copy_node_a.pool_d);
}

// method: clear
//
// arguments:
//  Integral::CMODE cmode: (input) clear mode
//
// return: logical error status
//
// clear the contents of the ContextPool
//
boolean ContextPool::clear(Integral::CMODE cmode_a) {

  // declare local variables
  //
  Vector<Context> keys;
  Context* ptr = (Context*)NULL;
  
  // free the allocated context objects
  //
  pool_d.keys(keys);
  for (long i=0; i < keys.length(); i++) {
    pool_d.remove(keys(i), ptr);
    delete ptr;
    ptr = (Context*)NULL;
  }

  // clear the pool
  //
  pool_d.clear(cmode_a);

  // set the allocation mode
  //
  pool_d.setAllocationMode(DstrBase::USER);

  // set the context pool capacity
  //
  pool_d.setCapacity(DEF_CAPACITY);
  
  // exit gracefully
  //
  return true;
}

// method: eq
//
// arguments:
//  const ContextPool& compare_node: (input) ContextPool to compare
//
// return: true if the ContextPools are equivalent, else false
//
// compare two ContextPools. they are equivalent if they have equivalent history
// objects
//
boolean ContextPool::eq(const ContextPool& compare_node_a) const {
  
  // compare the address
  //
  return (pool_d.eq(compare_node_a.pool_d));
}

// method: initAndAllocate
//
// arguments: none
//
// return: logical error status
//
// method creates a new context object and inserts it in the existing pool
//
Context* ContextPool::initAndAllocate() {

  // declare local variables
  //
  Context* ptr = (Context*)NULL;  
  Context* new_obj = (Context*)NULL;

  // allocate memory for the new object
  //
  new_obj = new Context();

  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {

    delete new_obj;
    new_obj = ptr;
  }

  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }
  
  // return the object
  //
  return new_obj;
}

// method: shiftAndAllocate
//
// arguments:
//  const Context* obj: (input) old context object
//  GraphVertex<SearchNode>* ver: (input) vertex to be shifted in the context
//
// return: logical error status
//
// method creates a new context object and inserts it in the existing pool
//
Context* ContextPool::shiftAndAllocate(const Context* obj_a,
				       GraphVertex<SearchNode>* ver_a) {
  
  // declare local variables
  //
  Context* ptr = (Context*)NULL;  
  Context* new_obj = (Context*)NULL;

  // allocate memory for the new object
  //
  new_obj = new Context(*obj_a);
  
  // shift the input value into the context
  //
  new_obj->assignAndAdvance((ulong)ver_a);
  
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {
    
    delete new_obj;
    new_obj = ptr;
  }
  
  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }    
  
  // return the object
  //
  return new_obj;
}

// method: foldAndAllocate
//
// arguments:
//  const Context* obj: (input) context object
//
// return: unique reference to the object
//
// returns a pointer to the input object
//
Context* ContextPool::foldAndAllocate(const Context* obj_a) {

  // declare local variables
  //
  Context* ptr = (Context*)NULL;
  
  // check and see if this object exists in the pool
  //
  Context* new_obj = new Context(*obj_a);
  new_obj->fold();
  
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {
    delete new_obj;
    new_obj = ptr;
  } else {
    pool_d.insert(*new_obj, new_obj);    
  }
  
  // exit gracefully
  //
  return new_obj;
}

// method: extendAndAllocate
//
// arguments:
//  const Context* obj: (input) context object
//  GraphVertex<SearchNode>* ver: (input) vertex to extended with
//
// return: unique reference to the object
//
// returns a pointer to the input object
//
Context* ContextPool::extendAndAllocate(const Context* obj_a,
					GraphVertex<SearchNode>* ver_a) {

  // declare local variables
  //
  Context* ptr = (Context*)NULL;
  
  // check and see if this object exists in the pool
  //
  Context* new_obj = new Context(*obj_a);
  new_obj->extend(ver_a);
  
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {
    delete new_obj;
    new_obj = ptr;
  } else {
    pool_d.insert(*new_obj, new_obj);    
  }
  
  // exit gracefully
  //
  return new_obj;
}

// method: get
//
// arguments:
//  const Context& obj: (input) context object
//
// return: unique reference to the object
//
// returns a pointer to the input object
//
Context* ContextPool::get(const Context& obj_a) {

  // declare local variables
  //
  Context* ptr = (Context*)NULL;
  
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(obj_a)) == (Context*)NULL) {
    ptr = new Context(obj_a);
    pool_d.insert(obj_a, ptr);    
  }
  
  // exit gracefully
  //
  return ptr;
}

// method: setCentralAndAllocate
//
// arguments:
//  const Context* obj: (input) old context object
//  GraphVertex<SearchNode>* ver: (input) vertex to be shifted in the context
//
// return: logical error status
//
// method creates a new context object and inserts it in the existing pool
//
Context* ContextPool::setCentralAndAllocate(const Context* obj_a,
					    GraphVertex<SearchNode>* ver_a) {
  
  // declare local variables
  //
  Context* ptr = (Context*)NULL;  
  Context* new_obj = (Context*)NULL;

  // allocate memory for the new object
  //
  new_obj = new Context(*obj_a);
  
  // shift the input value into the context
  //
  new_obj->setCentralVertex((ulong)ver_a);
  
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {
    
    delete new_obj;
    new_obj = ptr;
  }
  
  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }    
  
  // return the object
  //
  return new_obj;
}

// method: setLastAndAllocate
//
// arguments:
//  const Context* obj: (input) old context object
//  GraphVertex<SearchNode>* ver: (input) vertex to be shifted in the context
//
// return: logical error status
//
// method creates a new context object and inserts it in the existing pool
//
Context* ContextPool::setLastAndAllocate(const Context* obj_a,
					    GraphVertex<SearchNode>* ver_a) {
  
  // declare local variables
  //
  Context* ptr = (Context*)NULL;  
  Context* new_obj = (Context*)NULL;

  // allocate memory for the new object
  //
  new_obj = new Context(*obj_a);
  
  // shift the input value into the context
  //
  new_obj->setLastVertex((ulong)ver_a);
  
  // check and see if this object exists in the pool
  //
  if ((ptr = pool_d.get(*new_obj)) != (Context*)NULL) {
    
    delete new_obj;
    new_obj = ptr;
  }
  
  // insert the new object into the pool if it is not there already
  //
  else {
    
    pool_d.insert(*new_obj, new_obj);
  }    
  
  // return the object
  //
  return new_obj;
}


