-
+/** @file */
////////////////////////////////////////////////////////////////////////////////////////
//
// This file is part of Boost Statechart Viewer.
using namespace std;
+/**
+* This class provides saving information about state machine to a specified output file. It saves states and transitions and also it creates the transition table.
+*/
class IO_operations
-{
- list<string> transitions;
- list<string> states;
- list<string> events;
- string outputFilename;
+{
+ list<string> transitions; /** list of transitions */
+ list<string> states; /** list of states */
+ list<string> events; /** list of events */
+ string outputFilename;
string name_of_machine;
string name_of_first_state;
- string *table;
+ string *table; /** transition table. It is being allocated when starting the creation of output file. */
int nState;
int cols, rows;
+ /** This function finds place in the transition table to put a transition there. */
int find_place(string model, int type)
{
if(type == 1)
{
- for(unsigned i = 3;i<events.size()+3;i++)
+ for(int i = 3;i<cols;i++)
{
if(model.compare(0,model.size(),table[i])==0) return i;
}
}
else
{
- for(unsigned i = 1;i<states.size()+1;i++)
+ for(int i = 1;i<rows;i++)
if(model.compare(0,model.size(),table[i*cols+2])==0) return i;
}
return -1;
}
public:
- IO_operations() {}
-
+ IO_operations() {} /** Implicit constructor */
+ /** Constructor that fill in all private variables in this class */
IO_operations( const string outputFile, const string FSM_name, const string firstState, const list<string> trans, const list<string> state, const list<string> ev )
{
outputFilename = outputFile;
states = state;
events = ev;
}
- ~IO_operations()
+
+ ~IO_operations() /** destructor. It deallocates the transition table.*/
{
- delete table;
+ delete [] table;
}
- // set methods
- void setEvents(list<string> events)
+
+ void setEvents(list<string> events) /** Set list of events to an attribute */
{
this->events = events;
}
- void setTransitions(list<string> transitions)
+ void setTransitions(list<string> transitions) /** Set list of transitions to an attribute */
{
this->transitions = transitions;
}
- void setStates(list<string> states)
+ void setStates(list<string> states) /** Set list of states to an attribute */
{
this->states = states;
}
- void setNameOfStateMachine(string name_of_FSM)
+ void setNameOfStateMachine(string name_of_FSM) /** Set name of FSM to an attribute */
{
name_of_machine = name_of_FSM;
}
- void setNameOfFirstState(string first_state)
+ void setNameOfFirstState(string first_state) /** Set name of start state to an attribute */
{
name_of_first_state = first_state;
}
- void setOutputFilename(string outputFilename)
+ void setOutputFilename(string outputFilename) /** Set name of an output file to an attribute */
{
this->outputFilename = outputFilename;
}
- // outputfile writing methods
- void write_states(ofstream& filestr) // write states
+ bool write_states(ofstream& filestr) /** This method write states to the output file and also to transition table. */
{
int pos1, pos2, cnt, subs;
nState = 1;
{
pos1 = state.find(",");
ctx = cut_namespaces(state.substr(pos1+1));
- if(ctx.compare(0,context.length(),context)==0)
+ if(ctx.compare(0,context.length(),context)==0 && context.length()==ctx.length())
{
str = cut_namespaces(state.substr(0,pos1));
- filestr<<str<<";\n";
+ if(str.compare(0,name_of_first_state.length(),name_of_first_state)==0 && name_of_first_state.length()==str.length())
+ {
+ filestr<<str<<" [peripheries=2];\n";
+ table[cols*nState] = "*";
+ }
+ else filestr<<str<<"\n";
table[cols*nState+2] = str;
table[cols*nState+1] = context;
nState+=1;
nstates.erase(i);
i--;
- if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
}
}
if(cnt==2)
pos1 = state.find(",");
pos2 = state.rfind(",");
ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
- if(ctx.compare(0,context.length(),context)==0)
+ if(ctx.compare(0,context.length(),context)==0 && context.length()==ctx.length())
{
str = cut_namespaces(state.substr(0,pos1));
- filestr<<str<<";\n";
+ if(str.compare(0,name_of_first_state.length(),name_of_first_state)==0 && name_of_first_state.length()==str.length())
+ {
+ filestr<<str<<" [peripheries=2];\n";
+ table[cols*nState] = "*";
+ }
+ else filestr<<str<<"\n";
table[cols*nState+2] = str;
table[cols*nState+1] = context;
- nState+=1;
- if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
+ nState+=1;
}
}
}
- filestr<<name_of_first_state<<" [peripheries=2] ;\n";
subs = 0;
while(!nstates.empty()) // substates ?
{
filestr<<"subgraph cluster"<<subs<<" {\n";
pos1 = state.find(",");
pos2 = state.rfind(",");
+ if(pos1 == pos2) return false;
context = cut_namespaces(state.substr(0,pos1));
filestr<<"label=\""<<context<<"\";\n";
sState = cut_namespaces(state.substr(pos2+1));
- filestr<<sState<<" [peripheries=2] ;\n";
nstates.pop_front();
for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++)
{
{
pos1 = state.find(",");
ctx = cut_namespaces(state.substr(pos1+1));
- if(ctx.compare(0,context.length(),context)==0)
+ if(ctx.compare(0,context.length(),context)==0 && context.length()==ctx.length())
{
str = cut_namespaces(state.substr(0,pos1));
- filestr<<str<<";\n";
+ if(str.compare(0,sState.length(),sState)==0 && sState.length()==str.length())
+ {
+ filestr<<str<<" [peripheries=2];\n";
+ table[cols*nState]="*";
+ }
+ else filestr<<str<<"\n";
table[cols*nState+2] = str;
table[cols*nState+1] = context;
nState+=1;
nstates.erase(i);
i--;
- if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
}
}
if(cnt==2)
pos1 = state.find(",");
pos2 = state.rfind(",");
ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
- if(ctx.compare(0,context.length(),context)==0)
+ if(ctx.compare(0,context.length(),context)==0 && context.length()==ctx.length())
{
str = cut_namespaces(state.substr(0,pos1));
- filestr<<str<<";\n";
+ if(str.compare(0,sState.length(),sState)==0 && sState.length()==str.length())
+ {
+ filestr<<str<<" [peripheries=2];\n";
+ table[cols*nState]="*";
+ }
+ else filestr<<str<<"\n";
table[cols*nState+2] = str;
table[cols*nState+1] = context;
nState+=1;
- if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
}
}
}
filestr<<"}\n";
subs+=1;
}
- return;
+ return true;
}
- void write_transitions(ofstream& filestr) // write transitions
+ void write_transitions(ofstream& filestr) /** Write transitions to the output file nad the transition table. */
{
int pos1, pos2;
string params, state, event, dest;
for(list<string>::iterator i = transitions.begin();i!=transitions.end();i++) // write all transitions
{
params = *i;
- pos1 = params.find(",");
- state = cut_namespaces(params.substr(0,pos1));
- filestr<<state<<"->";
- pos2 = params.rfind(",");
- dest = cut_namespaces(params.substr(pos2+1));
- filestr<<dest;
- event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
- filestr<<"[label=\""<<event<<"\"];\n";
- table[find_place(state,2)*cols+find_place(event,1)]=dest;
+ if(count(params,',')==2)
+ {
+ pos1 = params.find(",");
+ state = cut_namespaces(params.substr(0,pos1));
+ filestr<<state<<"->";
+ pos2 = params.rfind(",");
+ dest = cut_namespaces(params.substr(pos2+1));
+ filestr<<dest;
+ event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
+ filestr<<"[label=\""<<event<<"\"];\n";
+ table[find_place(state,2)*cols+find_place(event,1)]=dest;
+ }
}
return;
}
- void fill_table_with_events()
+ void fill_table_with_events() /** Fill the first row of the transition table with events. */
{
int j = 3;
for(list<string>::iterator i = events.begin();i!=events.end();i++)
}
}
- void save_to_file() // save state automaton to file
+ void save_to_file() /** Create output file stream and write there the name of state machine. It controls the whole process of writing into output files. */
{
if(!name_of_first_state.empty())
{
rows = states.size()+1;
table = new string [cols*rows];
fill_table_with_events();
- write_states(filestr);
+ if(!write_states(filestr))
+ {
+ cerr<<"Error during writing states.\n";
+ filestr<<"}";
+ filestr.close();
+ return;
+ }
write_transitions(filestr);
filestr<<"}";
filestr.close();
+ // call write_reactions();
print_table();
}
else cout<<"No state machine was found. So no output file was created.\n";
return;
}
- void print_table()
+ void print_table() /** This function prints the transition table. At first it counts the size of all columns. */
{
cout<<"\nTRANSITION TABLE\n";
unsigned * len = new unsigned[cols];
len[0] = 1;
string line = "-|---|-";
- for(unsigned i = 1; i<cols; i++)
+ for(int i = 1; i<cols; i++)
{
len[i] = 0;
- for(unsigned j = 0;j<rows;j++)
+ for(int j = 0;j<rows;j++)
{
if(len[i]<table[j*cols+i].length()) len[i] = table[j*cols+i].length();
}
line.append("-|-");
}
cout<<line<<"\n";
- for(unsigned i = 0; i<rows; i++)
+ for(int i = 0; i<rows; i++)
{
cout<<" | ";
- for(unsigned j = 0;j<cols;j++)
+ for(int j = 0;j<cols;j++)
{
cout.width(len[j]);
cout<<left<<table[i*cols+j]<<" | ";
cout<<"\n";
cout<<line<<"\n";
}
- delete len;
+ delete [] len;
}
- // method for printing statistics about state automaton
- void print_stats() // print statistics
+
+ void print_stats() /** Print short statistics about the state machine */
{
cout<<"\n"<<"Statistics: \n";
cout<<"Number of states: "<<states.size()<<"\n";