// file: $isip/class/dstr/BiColorHash/BiColorHashDiagnose.h
// version: $Id: BiColorHashDiagnose.h 7089 2001-06-18 18:12:07Z alphonso $
//

// make sure definitions are only made once
//
#ifndef ISIP_GVHASH_DIAGNOSE
#define ISIP_GVHASH_DIAGNOSE

// isip include files
//
#ifndef ISIP_GVHASH
#include "BiColorHash.h"
#endif

// BiColorHashDiagnose: a class that contains the diagnose method of BiColorHash class.
//
template<class TObject>
class BiColorHashDiagnose : public BiColorHash<TObject> {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  // default values
  //
    
  // default arguments to methods
  //
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // methods: name
  //
  static const String& name() {
    return BiColorHash<TObject>::name();
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // debug methods
  //  these methods are omitted since this class does not have data
  //  members and operations  
  //
  
  // destructor/constructor(s):
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // assign methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // operator= methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //  

  // i/o methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // equality methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // memory-management methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------

  //  these methods are omitted since this class does not have data
  //  members and operations
  //
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

}; 

// below are all the methods for the BiColorHashDiagnose template class
//

//-----------------------------------------------------------------------------
//
// required static methods
//
//-----------------------------------------------------------------------------

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
template<class TObject>
boolean BiColorHashDiagnose<TObject>::diagnose(Integral::DEBUG level_a) {
    
  //---------------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //---------------------------------------------------------------------------

  // output the class name
  //
  if (level_a > Integral::NONE) {
    SysString output(L"diagnosing class ");
    output.concat(name());
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }
 
  //--------------------------------------------------------------------------
  //
  // 1. required public methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods...\n");
    Console::increaseIndention();
  }

  // test the constructors
  //
  BiGraphVertex<Char> vert_00;
  BiColorHash<Char> hash_00;
  hash_00.insert(&vert_00, Integral::BLACK);
  BiColorHash<Char> hash_01(hash_00);

  if (hash_00.get(&vert_00) != Integral::BLACK) {
    return Error::handle(name(), L"constructor", Error::TEST,
			 __FILE__, __LINE__);    
  }

  if (hash_01.get(&vert_00) != Integral::BLACK) {
    return Error::handle(name(), L"constructor", Error::TEST,
			 __FILE__, __LINE__);    
  }
  
  if (hash_00.get(&vert_00) != hash_01.get(&vert_00)) {
    return Error::handle(name(), L"constructor", Error::TEST,
			 __FILE__, __LINE__);
  }

  // test assign methods
  //
  BiColorHash<Char> hash_02;
  hash_02.assign(hash_00);

  if (hash_02.get(&vert_00) != Integral::BLACK) {
    return Error::handle(name(), L"assign", Error::TEST,
			 __FILE__, __LINE__);    
  }  

  // test operator= and equality methods
  //
  BiColorHash<Char> hash_03;
  hash_03 = hash_02;

  if (level_a > Integral::BRIEF) {
    hash_03.debug(L"hash_03");
  }
  
  if (!hash_03.eq(hash_00)) {
    return Error::handle(name(), L"eq", Error::TEST,
			 __FILE__, __LINE__);    
  }    
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //--------------------------------------------------------------------------
  //
  // 2. hash table property methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing hash table property methods...\n");
    Console::increaseIndention();
  }

  // create a hash table
  //
  BiColorHash<Char> hash_04;

  // test the isEmpty method
  //
  if (!hash_04.isEmpty()) {
    return Error::handle(name(), L"isEmpty", Error::TEST,
			 __FILE__, __LINE__);
  }

  // create some data
  //
  BiGraphVertex<Char> vert_01;
  BiGraphVertex<Char> vert_02;

  // add some vertices to the hash table
  //
  hash_04.insert(&vert_01, Integral::GREEN);
  hash_04.insert(&vert_02, Integral::WHITE);

  // test the getNumItems method
  //
  if (hash_04.getNumItems() != (long)2) {
    return Error::handle(name(), L"getNumItems()", Error::TEST,
			 __FILE__, __LINE__);        
  }

  // test the isEmpty method
  //
  if (hash_04.isEmpty()) {
    return Error::handle(name(), L"isEmpty", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //--------------------------------------------------------------------------
  //
  // 3. hash table get and set methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing hash table get and set methods...\n");
    Console::increaseIndention();
  }

  // declare a hash table
  //
  BiColorHash<Char> hash_05;
  
  // create some data
  //
  BiGraphVertex<Char> vert_03;
  BiGraphVertex<Char> vert_04;
  BiGraphVertex<Char> vert_05;  
  BiGraphVertex<Char> vert_06;
  BiGraphVertex<Char> vert_07;

  // add some vertices to teh hash table
  //
  hash_05.insert(&vert_01, Integral::GREEN);
  hash_05.insert(&vert_02, Integral::WHITE);
  hash_05.insert(&vert_03, Integral::GREY);
  hash_05.insert(&vert_04, Integral::BLACK);
  hash_05.insert(&vert_05, Integral::BLUE);  
  hash_05.insert(&vert_06, Integral::BLUE);  
  hash_05.insert(&vert_07, Integral::GREY);

  // test the get methods
  //
  if (hash_05.get(&vert_02) != Integral::WHITE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_05.get(&vert_04) != Integral::BLACK) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_05.get(&vert_01) != Integral::GREEN) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }    
  if (hash_05.get(&vert_03) != Integral::GREY) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_05.get(&vert_05) != Integral::BLUE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_05.get(&vert_06) != Integral::BLUE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }    
  if (hash_05.get(&vert_07) != Integral::GREY) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }

  // test the set methods
  //
  hash_05.set(&vert_02, Integral::BLUE);
  if (hash_05.get(&vert_02) != Integral::BLUE) {
    return Error::handle(name(), L"set/get", Error::TEST,
			 __FILE__, __LINE__);    
  }

  hash_05.set(&vert_02, Integral::WHITE);
  if (hash_05.get(&vert_02) != Integral::WHITE) {
    return Error::handle(name(), L"set/get", Error::TEST,
			 __FILE__, __LINE__);    
  }

  hash_05.set(&vert_06, Integral::GREY);
  if (hash_05.get(&vert_06) != Integral::GREY) {
    return Error::handle(name(), L"set/get", Error::TEST,
			 __FILE__, __LINE__);    
  }

  hash_05.set(&vert_06, Integral::WHITE);
  if (hash_05.get(&vert_06) != Integral::WHITE) {
    return Error::handle(name(), L"set/get", Error::TEST,
			 __FILE__, __LINE__);    
  }  
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }  

  //--------------------------------------------------------------------------
  //
  // 4. hash table insert and remove methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing hash table insert and remove methods...\n");
    Console::increaseIndention();
  }

  // declare a hash table
  //
  BiColorHash<Char> hash_06;
  
  // insert some vertices to teh hash table
  //
  hash_06.insert(&vert_01, Integral::GREEN);
  hash_06.insert(&vert_02, Integral::WHITE);
  hash_06.insert(&vert_03, Integral::GREY);
  hash_06.insert(&vert_04, Integral::BLACK);
  hash_06.insert(&vert_05, Integral::BLUE);  
  hash_06.insert(&vert_06, Integral::BLUE);  
  hash_06.insert(&vert_07, Integral::GREY);

  // test the insert methods
  //
  if (hash_06.get(&vert_02) != Integral::WHITE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_06.get(&vert_04) != Integral::BLACK) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_06.get(&vert_01) != Integral::GREEN) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }    
  if (hash_06.get(&vert_03) != Integral::GREY) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_06.get(&vert_05) != Integral::BLUE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }
  if (hash_06.get(&vert_06) != Integral::BLUE) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }    
  if (hash_06.get(&vert_07) != Integral::GREY) {
    return Error::handle(name(), L"insert/get", Error::TEST,
			 __FILE__, __LINE__);    
  }

  // test the remove methods
  //
  hash_06.remove(&vert_01);
  hash_06.remove(&vert_02);
  hash_06.remove(&vert_03);
  hash_06.remove(&vert_06);

  if (hash_06.containsKey(&vert_03)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_06.containsKey(&vert_06)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_06.containsKey(&vert_01)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_06.containsKey(&vert_02)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //--------------------------------------------------------------------------
  //
  // 5. hash table contains methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing hash table contains methods...\n");
    Console::increaseIndention();
  }

  // declare a hash table
  //
  BiColorHash<Char> hash_07;
  
  // insert some vertices to teh hash table
  //
  hash_07.insert(&vert_01, Integral::GREEN);
  hash_07.insert(&vert_02, Integral::GREY);
  hash_07.insert(&vert_03, Integral::GREY);
  hash_07.insert(&vert_04, Integral::BLACK);

  // test the containsKey method
  //  
  if (!hash_07.containsKey(&vert_01)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!hash_07.containsKey(&vert_02)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!hash_07.containsKey(&vert_03)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!hash_07.containsKey(&vert_04)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (hash_07.containsKey(&vert_05)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_07.containsKey(&vert_06)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_07.containsKey(&vert_07)) {
    return Error::handle(name(), L"containsKey", Error::TEST,
			 __FILE__, __LINE__);
  }      

  // test the containsValue method
  //    
  if (!hash_07.containsValue(Integral::GREY)) {
    return Error::handle(name(), L"containsValue", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!hash_07.containsValue(Integral::GREEN)) {
    return Error::handle(name(), L"containsValue", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!hash_07.containsValue(Integral::BLACK)) {
    return Error::handle(name(), L"containsValue", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  if (hash_07.containsValue(Integral::WHITE)) {
    return Error::handle(name(), L"containsValue", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (hash_07.containsValue(Integral::BLUE)) {
    return Error::handle(name(), L"containsValue", Error::TEST,
			 __FILE__, __LINE__);
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }  
  

  //---------------------------------------------------------------------------
  //
  // 6. print completion message
  //
  //---------------------------------------------------------------------------

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  if (level_a > Integral::NONE) {
    SysString output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }  

  // exit gracefully
  //
  return true;
}

// end of include file
//
#endif
