/*******************************************************************
*
*  DESCRIPTION: class ProcessorAdmin
*
*  AUTHOR: Amir Barylko & Jorge Beyoglonian 
*
*  EMAIL: mailto://amir@dc.uba.ar
*         mailto://jbeyoglo@dc.uba.ar
*
*  DATE: 27/6/1998
*
*******************************************************************/

/** include files **/
#include "procadm.h"          // header
#include "simulat.h"          // class Simulator
#include "coordin.h"          // class Coordinator
#include "strutil.h"          // lowerCase
#include "root.h"             // class Root
#include "coorcell.h"         // CellCoordinator
#include "flatcoor.h"         // FlatCoordinator
#include "flatcoup.h"         // FlatCoupledCell

/** public data **/
const ProcId ProcessorAdmin::rootId( 0 ) ;

/** private data **/
ProcessorAdmin *SingleProcessorAdmin::instance( NULL ) ;

/** public functions **/
/*******************************************************************
* Function Name: ProcessorAdmin
********************************************************************/
ProcessorAdmin::ProcessorAdmin() 
: procIdCount( ProcessorAdmin::rootId + 1 )
{}

/*******************************************************************
* Function Name: ~ProcessorAdmin()
* Description: destroys all the alive processors
********************************************************************/
ProcessorAdmin::~ProcessorAdmin()
{
	for ( ProcessorDB::iterator cursor = procDB.begin(); cursor != procDB.end(); cursor++ )
		delete cursor->second;
}

/*******************************************************************
* Function Name: generateProcessor
********************************************************************/
Processor &ProcessorAdmin::generateProcessor( Atomic *atomic )
{
	Simulator *sim = new Simulator( atomic );
	add2DB( sim, newId() );
	return *sim;
}

/*******************************************************************
* Function Name: generateProcessor
********************************************************************/
Processor &ProcessorAdmin::generateProcessor( Coupled *coupled )
{
	Coordinator *coord = new Coordinator( coupled );
	add2DB( coord, newId() );
	return *coord;
}

/*******************************************************************
* Function Name: generateProcessor
********************************************************************/
Processor &ProcessorAdmin::generateProcessor( CoupledCell *coupled )
{
	Coordinator *coord = new CellCoordinator( coupled ) ;
	add2DB( coord, newId() ) ;
	return *coord ;
} 

/*******************************************************************
* Function Name: generateProcessor
********************************************************************/
Processor &ProcessorAdmin::generateProcessor( FlatCoupledCell *coupled )
{
	Coordinator *coord = new FlatCoordinator( coupled ) ;
	add2DB( coord, newId() ) ;
	return *coord ;
} 

/*******************************************************************
* Function Name: generateRoot
********************************************************************/
Processor &ProcessorAdmin::generateRoot()
{
	Root *root = new Root( ProcessorAdmin::rootId ) ;
	add2DB( root, ProcessorAdmin::rootId ) ;
	return *root ;
}

/*******************************************************************
* Function Name: processor
********************************************************************/
Processor &ProcessorAdmin::processor( const ProcId &id )
{
	ProcessorDB::iterator cursor( procDB.find( id ) );

	if( cursor == procDB.end() )
	{
		InvalidProcessorIdException e;
		e.addText( string( "The processor id " ) + id + " is invalid!" ) ;
		MTHROW( e ) ;
	}
	MASSERT( cursor->second );
	return *( cursor->second );
}

/*******************************************************************
* Function Name: processor
********************************************************************/
Processor &ProcessorAdmin::processor( const string &name )
{
	string lower( lowerCase( name ) ) ;

	ProcessorDB::iterator cursor( procDB.begin() );

	while( cursor != procDB.end() && cursor->second->description() != lower )
		cursor ++ ;

	if( cursor == procDB.end() )
	{
		InvalidProcessorIdException e ;
		e.addText( string( "The processor " ) + lowerCase( name ) + " is invalid!" );
		MTHROW( e ) ;
	}
	return *( cursor->second );
}

/*******************************************************************
* Function Name: add2DB
********************************************************************/
ProcessorAdmin &ProcessorAdmin::add2DB( Processor *newProc, const ProcId &newId )
{
	newProc->id( newId );
	procDB[ newId ] = newProc;
	return *this;
}
