/*************************************************************************************************
** Project:     FSMGenerator
** Package:     FSMGenerator
** Module:      FSMGenerator::generator
** File:        FSMCppGenerator.cpp
** Date:        2002.08.01
** Author:      Pavel Bekkerman (chpavel@tx.technion.ac.il)
** Copyright:   Copyright (C) 2002 Pavel Bekkerman
** License:
**              This program is free software; you can redistribute it and/or
**              modify it under the terms of the GNU General Public License as
**              published by the Free Software Foundation; either version 2 of
**              the License, or (at your option) any later version.
**
**              This program is distributed in the hope that it will be useful,
**              but WITHOUT ANY WARRANTY; without even the implied warranty of
**              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**              GNU General Public License for more details.
**
**              You should have received a copy of the GNU General Public License
**              along with this program; if not, write to the Free Software
**              Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
**
** Contact:     Pavel Bekkerman (chpavel@tx.technion.ac.il)
*************************************************************************************************/

#include "FSMCppGenerator.h"

using namespace std;

const string STATE_FILE_NAME = "FSMIDStates";
const string EVENT_FILE_NAME = "FSMIDEvents";
const string TRANS_FILE_NAME = "FSMIDTransitions";
const string CALLS_FILE_NAME = "FSMIDCallbacks";

const string CPP_FILE_EXT    = ".cpp";
const string HEADER_FILE_EXT = ".h";

#define    FSM_CPP_FILE_NAME        (m_fsmDb.Name() + CPP_FILE_EXT)
#define    FSM_HPP_FILE_NAME        (m_fsmDb.Name() + HEADER_FILE_EXT)

// ********************************************************************* FSMCPPGenerator

// *********************************************** Constructor
FSMGenerator::FSMCPPGenerator::FSMCPPGenerator(const FSMDB& fsmDb, const string& strPath)
			: FSMFileGenerator(fsmDb,strPath)
{
}

// *********************************************** Destructor

FSMGenerator::FSMCPPGenerator::~FSMCPPGenerator()
{
}

// *********************************************** File Generators

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _stateFileGenerator

bool
FSMGenerator::FSMCPPGenerator::_stateFileGenerator()const
{
	const string strFileName = m_strDestinationPath + STATE_FILE_NAME + HEADER_FILE_EXT;

	ofstream file(strFileName.c_str(),ios::trunc);
	if(!file)
		return false;

	string strDefine = m_fsmDb.Name();

	for(int c=0; c < strDefine.size(); ++c)
		strDefine[c] = toupper(strDefine[c]);

	file<<"#ifndef _"<<strDefine<<"STATES_H"<<endl;
	file<<"#define _"<<strDefine<<"STATES_H"<<endl<<endl<<endl;


	file<<"/*****************************************"	<<endl
		<<"* Title: FSMIDStates Interface"					<<endl
		<<"* Description: State Enumerator interface."	<<endl
		<<"******************************************/"	<<endl
		<<endl
		<<"// created from configuration file"<<endl
		<<endl;

	file<<"using namespace FSMApi;"<<endl<<endl;

	file<<"namespace "<<m_fsmDb.Name()<<"\n{"<<endl<<endl;

	file<<"\tenum FSMIDStates"<<endl
		<<"\t{"<<endl;

	file<<"\t\t"<<STATE_PRE<<",\t\t// the NULL State."<<endl;	

	int state;
	for( state = 0; state < m_fsmDb.m_dvStates.size()-1; ++state )
		file<<"\t\t"<<STATE_PRE<<m_fsmDb.m_dvStates[state].Name()<<','<<endl;

	file<<"\t\t"<<STATE_PRE<<m_fsmDb.m_dvStates[state].Name()<<endl;


	file<<"\t};\n\n"<<endl;

	file<<"}\t// namespace "<<m_fsmDb.Name()<<endl;

	file<<"\n\n\n#endif\t//"<<strDefine<<"STATES_H"<<endl;

	return true;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _eventFileGenerator

bool
FSMGenerator::FSMCPPGenerator::_eventFileGenerator()const
{
	const string strFileName = m_strDestinationPath + EVENT_FILE_NAME + HEADER_FILE_EXT;

	ofstream file(strFileName.c_str(),ios::trunc);
	if(!file)
		return false;

	string strDefine = m_fsmDb.Name();

	for(int c=0; c < strDefine.size(); ++c)
		strDefine[c] = toupper(strDefine[c]);

	file<<"#ifndef _"<<strDefine<<"EVENTS_H"<<endl;
	file<<"#define _"<<strDefine<<"EVENTS_H"<<endl<<endl<<endl;

	file<<"/*****************************************"	<<endl
		<<"* Title: FSMIDEvents Interface"					<<endl
		<<"* Description: Event Enumerator interface."	<<endl
		<<"******************************************/"	<<endl
		<<endl
		<<"// created from configuration file"<<endl
		<<endl;

	file<<"namespace "<<m_fsmDb.Name()<<"\n{"<<endl<<endl;

	file<<"\tenum FSMIDEvents"<<endl
		<<"\t{"<<endl;

	file<<"\t\t"<<EVENT_PRE<<",\t\t// the NULL Event."<<endl;	

	int event;
	for( event = 0; event < m_fsmDb.m_dvEvents.size()-1; ++event )
		file<<"\t\t"<<EVENT_PRE<<m_fsmDb.m_dvEvents[event].Name()<<','<<endl;

	file<<"\t\t"<<EVENT_PRE<<m_fsmDb.m_dvEvents[event].Name()<<endl;


	file<<"\t};\n\n"<<endl;

	file<<"}\t// namespace "<<m_fsmDb.Name()<<endl;

	file<<"\n\n\n#endif\t//"<<strDefine<<"EVENTS_H"<<endl;

	return true;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _transFileGenerator

bool
FSMGenerator::FSMCPPGenerator::_transFileGenerator()const
{
	const string strFileName = m_strDestinationPath + TRANS_FILE_NAME + HEADER_FILE_EXT;

	ofstream file(strFileName.c_str(),ios::trunc);
	if(!file)
		return false;

	string strDefine = m_fsmDb.Name();

	for(int c=0; c < strDefine.size(); ++c)
		strDefine[c] = toupper(strDefine[c]);

	file<<"#ifndef _"<<strDefine<<"TRANSITIONS_H"<<endl;
	file<<"#define _"<<strDefine<<"TRANSITIONS_H"<<endl<<endl<<endl;


	file<<"/**********************************************"	<<endl
		<<"* Title: FSMIDTransitions Interface"				<<endl
		<<"* Description: Transition Enumerator interface."	<<endl
		<<"***********************************************/"<<endl
		<<endl
		<<"// created from configuration file"<<endl
		<<endl;

	file<<"namespace "<<m_fsmDb.Name()<<"\n{"<<endl<<endl;

	file<<"\tenum FSMIDTransitions"<<endl
		<<"\t{"<<endl;

	file<<"\t\t"<<TRANS_PRE<<",\t\t// the NULL Transition."<<endl;	

	int trans;
	for( trans = 0; trans < m_fsmDb.m_dvTransitions.size()-1; ++trans )
		file<<"\t\t"<<TRANS_PRE<<m_fsmDb.m_dvTransitions[trans].Name()<<','<<endl;

	file<<"\t\t"<<TRANS_PRE<<m_fsmDb.m_dvTransitions[trans].Name()<<endl;


	file<<"\t};\n\n"<<endl;

	file<<"}\t// namespace "<<m_fsmDb.Name()<<endl;

	file<<"\n\n\n#endif\t//"<<strDefine<<"TRANSITIONS_H"<<endl;

	return true;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _callsFileGenerator

bool
FSMGenerator::FSMCPPGenerator::_callsFileGenerator()const
{
	const string strFileName = m_strDestinationPath + CALLS_FILE_NAME + HEADER_FILE_EXT;

	ofstream file(strFileName.c_str(),ios::trunc);
	if(!file)
		return false;

	string strDefine = m_fsmDb.Name();

	for(int c=0; c < strDefine.size(); ++c)
		strDefine[c] = toupper(strDefine[c]);

	file<<"#ifndef _"<<strDefine<<"CALLBACKS_H"<<endl;
	file<<"#define _"<<strDefine<<"CALLBACKS_H"<<endl<<endl<<endl;

	file<<"/********************************************"	<<endl
		<<"* Title: FSMIDCallbacks Interface"					<<endl
		<<"* Description: Callback Enumerator interface."	<<endl
		<<"*********************************************/"	<<endl
		<<endl
		<<"// created from configuration file"<<endl
		<<endl;

	file<<"namespace "<<m_fsmDb.Name()<<"\n{"<<endl<<endl;

	file<<"\tenum FSMIDCallbacks"<<endl
		<<"\t{"<<endl;

	file<<"\t\t"<<CALL_PRE<<",\t\t// the NULL Callback."<<endl;	

	int call;
	for( call = 1; call < m_fsmDb.m_dvCallbacks.size()-1; ++call )
		file<<"\t\t"<<CALL_PRE<<m_fsmDb.m_dvCallbacks[call].Name()<<','<<endl;

	file<<"\t\t"<<CALL_PRE<<m_fsmDb.m_dvCallbacks[call].Name()<<endl;


	file<<"\t};\n\n"<<endl;

	file<<"}\t// namespace "<<m_fsmDb.Name()<<endl;

	file<<"\n\n\n#endif\t//"<<strDefine<<"CALLBACKS_H"<<endl;

	return true;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainFileGenerator

bool
FSMGenerator::FSMCPPGenerator::_mainFileGenerator()const
{
	////////////////////////////////////////////
	// header generation.

	const string strHeaderFileName = m_strDestinationPath+FSM_HPP_FILE_NAME;

	ofstream file(strHeaderFileName.c_str(),ios::trunc);
	if(!file)
		return false;

	string strDefine = m_fsmDb.Name();

	for(int c=0; c < strDefine.size(); ++c)
		strDefine[c] = toupper(strDefine[c]);

	file<<"#ifndef _"<<strDefine<<"_H"<<endl;
	file<<"#define _"<<strDefine<<"_H"<<endl<<endl<<endl;

	file<<"/******************************************"	<<endl
		<<"* Title: class "<<m_fsmDb.Name()				<<endl
		<<"* Description: The main class of the FSM"	<<endl
		<<"*******************************************/"<<endl
		<<endl
		<<"// created from configuration file"<<endl
		<<endl;

	file<<"#include \"AbstractFSM" + HEADER_FILE_EXT + "\""<<endl;
	file<<"#include \"FSMIDPair" + HEADER_FILE_EXT + "\""<<endl;
	file<<"#include \"FSMException" + HEADER_FILE_EXT + "\""<<endl;

	file<<"#include \""<<STATE_FILE_NAME + HEADER_FILE_EXT<<'\"'<<endl;
	file<<"#include \""<<EVENT_FILE_NAME + HEADER_FILE_EXT<<'\"'<<endl;
	file<<"#include \""<<TRANS_FILE_NAME + HEADER_FILE_EXT<<'\"'<<endl;
	file<<"#include \""<<CALLS_FILE_NAME + HEADER_FILE_EXT<<'\"'<<endl;
	file<<endl<<endl;

	file<<"namespace "<<m_fsmDb.Name()<<"\n{"<<endl<<endl;

	// FSM class declaration
	file<<"\tclass "<<m_fsmDb.Name()<<" : public AbstractFSM"<<endl
		<<"\t{"<<endl
		<<"\t\tpublic:\n"<<endl;

	
	file<<"\t\t\t"<<m_fsmDb.Name()<<" () {}"<<endl	// constructor 
		<<"\t\t\t~"<<m_fsmDb.Name()<<"() {}\n"<<endl;	// distructor.

	// function declarations
	file	<<"\t\t\tint\t_getStartState\t\t() throw();"<<endl
		<<"\t\t\tFSMIDPair\t_getNextIncarnation\t( int idState, int idEvent ) throw();"<<endl
		<<"\t\t\tbool\t_isFinalState\t\t( int idState ) throw();"<<endl
		<<"\t\t\tvoid\t_processStateEnter\t( int idState ) throw();"<<endl
		<<"\t\t\tvoid\t_processStateExit\t( int idState ) throw();"<<endl
		<<"\t\t\tvoid\t_processEvent\t\t( int idEvent ) throw();"<<endl
		<<"\t\t\tvoid\t_processTransition\t( int idTransition ) throw();"<<endl
		<<"\t\t\tvoid\t_processCallback\t( int idCallback ) throw();"<<endl;

	file<<"\n\t};\t //class "<<m_fsmDb.Name()<<endl;

	// end of class declaration

	file<<"\n\n}\t// namespace "<<m_fsmDb.Name()<<endl;

	file<<"\n\n\n#endif\t//"<<'_'<<strDefine<<"_H"<<endl;

	file.close();

	// end of header generation .

	////////////////////////////////////////////
	// cpp generation.

	const string strCPPFileName = m_strDestinationPath+FSM_CPP_FILE_NAME;
	file.open(strCPPFileName.c_str(),ios::trunc);

	file<<"#include \""<<FSM_HPP_FILE_NAME<<'\"'<<endl<<endl;

	file<<"// ****************************************** class "<<m_fsmDb.Name()<<" functions.\n"<<endl;
	// generate all member functions.

	_mainGetStartStateGenerator		(file);
	file<<endl;
	_mainGetNextIncarnationGenerator(file);
	file<<endl;
	_mainIsFinalStateGenerator		(file);
	file<<endl;
	_mainProcessStateEnterGenerator	(file);
	file<<endl;
	_mainProcessStateExitGenerator	(file);
	file<<endl;
	_mainProcessEventGenerator		(file);
	file<<endl;
	_mainProcessTransitionGenerator	(file);
	file<<endl;
	_mainProcessCallbackGenerator	(file);
	file<<endl;

	// end of FSM class.
	return true;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainGetStartState

void
FSMGenerator::FSMCPPGenerator::_mainGetStartStateGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _getStartState\n"<<endl;

	file<<"int\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_getStartState() throw()\n"
		<<"{\n"
		<<"\treturn STATE_"<<m_fsmDb.m_dvStates[m_fsmDb.m_indStart].Name()<<";\n"
		<<"}\n";	
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainGetNextIncarnation

void
FSMGenerator::FSMCPPGenerator::_mainGetNextIncarnationGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _getNextIncarnation\n"<<endl;

	file<<"FSMIDPair\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_getNextIncarnation( int idState, int idEvent ) throw()\n"
		  "{\n"
		  "\tFSMIDPair idpair;\n\n"
		  "\tswitch( idState )\n"
		  "\t{"<<endl;

	int state;
	for( state = 0; state<m_fsmDb.m_dvStates.size(); ++state )
	{
		const State& current = m_fsmDb.m_dvStates[state];
		file<<"\t\tcase STATE_"<<current.Name()<<":\n";
		file<<"\t\t\tswitch( idEvent )\n"
			  "\t\t\t{"<<endl;
		list<INDEX>::const_iterator citr;
		for(citr = current.transitions.begin(); citr != current.transitions.end(); ++citr)
		{
			const Transition& trans = m_fsmDb.m_dvTransitions[*citr];
			file<<"\t\t\t\tcase EVENT_"<<m_fsmDb.m_dvEvents[trans.WithEvent()].Name()<<":\n"
				  "\t\t\t\t\tidpair.idFirst  = TRANSITION_"<<trans.Name()<<";\n"
				  "\t\t\t\t\tidpair.idSecond = STATE_"<<m_fsmDb.m_dvStates[trans.ToState()].Name()<<";\n"
			      "\t\t\t\tbreak;\n"<<endl;
		}

		file<<"\t\t\t\tdefault:\n"
              "\t\t\t\t\tthrow new FSMException( \"Illegal event.\" );\n"
			  "\t\t\t}\n"
			  "\t\tbreak;\n"<<endl;
	}

	file<<"\t\tdefault:\n"
          "\t\t\tthrow new FSMException( \"Illegal state.\" );\n"
		  "\t}\n"<<endl;

	file<<"\t return idpair;\n"
		  "}\n";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainIsFinalStateGenerator

void
FSMGenerator::FSMCPPGenerator::_mainIsFinalStateGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _isFinalState\n"<<endl;

	file<<"bool\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_isFinalState( int idState ) throw()\n"
		"{\n"
		"\tswitch( idState )\n"
		"\t{\n";

	int state;
	for( state=0; state < m_fsmDb.m_dvStates.size(); ++state )
		if(m_fsmDb.m_dvStates[state].IsFinal())
			file<<"\t\tcase STATE_"<<m_fsmDb.m_dvStates[state].Name()<<":\n";
	file<<"\t\t\treturn true;\n"<<endl;

	for( state=0; state < m_fsmDb.m_dvStates.size(); ++state )
		if(!m_fsmDb.m_dvStates[state].IsFinal())
			file<<"\t\tcase STATE_"<<m_fsmDb.m_dvStates[state].Name()<<":\n";
	file<<"\t\t\treturn false;\n"<<endl;

	file<<"\t\tdefault:\n"
		  "\t\t\tthrow new FSMException( \"Illegal state.\" );\n";
	file<<"\t}\n"
		  "}\n";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainProcessStateEnterGenerator

void
FSMGenerator::FSMCPPGenerator::_mainProcessStateEnterGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _processStateEnter\n"<<endl;

	file<<"void\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_processStateEnter( int idState ) throw()\n"
		  "{\n"
		  "\ttry\n"
		  "\t{\n"
		  "\t\tswitch( idState )\n"
		  "\t\t{\n";

	int state;
	for( state=0; state < m_fsmDb.m_dvStates.size(); ++state )
	{
		const State& current = m_fsmDb.m_dvStates[state];
		file<<"\t\t\tcase STATE_"<<current.Name()<<":\n"
			  "\t\t\t\t_processCallback( CALLBACK_"<<m_fsmDb.m_dvCallbacks[current.EnterCall()].Name()<<" );\n"
			  "\t\t\tbreak;\n"<<endl;
	}
    file<<"\t\t\tdefault:\n"
		  "\t\t\t\tthrow new FSMException( \"Illegal state.\" );\n"
		  "\t\t}\n"
		  "\t}\n"
		  "\tcatch( FSMException e )\n"
		  "\t{\n"
		  "\t\tthrow e;\n"
		  "\t}\n"
		  "}\n";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainProcessStateExitGenerator

void
FSMGenerator::FSMCPPGenerator::_mainProcessStateExitGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _processStateExit\n"<<endl;

	file<<"void\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_processStateExit( int idState ) throw()\n"
		  "{\n"
		  "\ttry\n"
		  "\t{\n"
		  "\t\tswitch( idState )\n"
		  "\t\t{\n";

	int state;
	for( state=0; state < m_fsmDb.m_dvStates.size(); ++state )
	{
		const State& current = m_fsmDb.m_dvStates[state];
		file<<"\t\t\tcase STATE_"<<current.Name()<<":\n"
			  "\t\t\t\t_processCallback( CALLBACK_"<<m_fsmDb.m_dvCallbacks[current.ExitCall()].Name()<<" );\n"
			  "\t\t\tbreak;\n"<<endl;
	}
    file<<"\t\t\tdefault:\n"
		  "\t\t\t\tthrow new FSMException( \"Illegal state.\" );\n"
		  "\t\t}\n"
		  "\t}\n"
		  "\tcatch( FSMException e )\n"
		  "\t{\n"
		  "\t\tthrow e;\n"
		  "\t}\n"
		  "}\n";
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainProcessEventGenerator

void
FSMGenerator::FSMCPPGenerator::_mainProcessEventGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _processEvent\n"<<endl;

	file<<"void\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_processEvent( int idEvent ) throw()\n"
		  "{\n"
		  "\ttry\n"
		  "\t{\n"
		  "\t\tswitch( idEvent )\n"
		  "\t\t{\n";
	for(int event=0; event < m_fsmDb.m_dvEvents.size(); ++event)
	{
		const Event& current = m_fsmDb.m_dvEvents[event];
		file<<"\t\t\tcase EVENT_"<<current.Name()<<":\n"
			  "\t\t\t\t_processCallback( CALLBACK_"<<m_fsmDb.m_dvCallbacks[current.Callback()].Name()<<" );\n"
			  "\t\t\tbreak;\n"<<endl;
	}
    file<<"\t\t\tdefault:\n"
		  "\t\t\t\tthrow new FSMException( \"Illegal event.\" );\n"
		  "\t\t}\n"
		  "\t}\n"
		  "\tcatch( FSMException e )\n"
		  "\t{\n"
		  "\t\tthrow e;\n"
		  "\t}\n"
		  "}\n";
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainProcessTransitionGenerator

void
FSMGenerator::FSMCPPGenerator::_mainProcessTransitionGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _processTransition\n"<<endl;

	file<<"void\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_processTransition( int idTransition ) throw()\n"
		  "{\n"
		  "\ttry\n"
		  "\t{\n"
		  "\t\tswitch( idTransition )\n"
		  "\t\t{\n";
	for(int trans=0; trans < m_fsmDb.m_dvTransitions.size(); ++trans)
	{
		const Transition& current = m_fsmDb.m_dvTransitions[trans];
		file<<"\t\t\tcase TRANSITION_"<<current.Name()<<":\n"
			  "\t\t\t\t_processCallback( CALLBACK_"<<m_fsmDb.m_dvCallbacks[current.Callback()].Name()<<" );\n"
			  "\t\t\tbreak;\n"<<endl;
	}
    file<<"\t\t\tdefault:\n"
		  "\t\t\t\tthrow new FSMException( \"Illegal transition.\" );\n"
		  "\t\t}\n"
		  "\t}\n"
		  "\tcatch( FSMException e )\n"
		  "\t{\n"
		  "\t\tthrow e;\n"
		  "\t}\n"
		  "}\n";
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _mainProcessCallbackGenerator

void
FSMGenerator::FSMCPPGenerator::_mainProcessCallbackGenerator(ofstream& file)const
{
	file<<"// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ _processCallback\n"<<endl;

	file<<"void\n"
		<<m_fsmDb.Name()<<"::"<<m_fsmDb.Name()<<"::_processCallback( int idCallback ) throw()\n"
		  "{\n"
		  "\tswitch( idCallback )\n"
		  "\t{\n";

	// add the case for the 'empty' callback.
	file<<"\t\tcase CALLBACK_:\n"
		  "\t\t\t// The 'NULL' callback - nothing to be done.\n"
		  "\t\tbreak;\n"<<endl;

	// PB: Add here callbacks preparation
	// by replacing "." with "::" - special Cpp case.

	for(int call=1; call < m_fsmDb.m_dvCallbacks.size(); ++call) // skip the 1st 'empty'.
	{
		const Callback& current = m_fsmDb.m_dvCallbacks[call];
		file<<"\t\tcase CALLBACK_"<<current.Name()<<":\n"
			  "\t\t\t"<<current.Function()<<"();\n"
			  "\t\tbreak;\n"<<endl;
	}

	file<<"\t\tdefault:\n"
          "\t\t\tthrow new FSMException( \"Illegal callback.\" );\n"
		  "\t}\n"
		  "\treturn;\n"
		  "}\n";
}

