2 ////////////////////////////////////////////////////////////////////////////////////////
4 // This file is part of Boost Statechart Viewer.
6 // Boost Statechart Viewer is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // Boost Statechart Viewer is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Boost Statechart Viewer. If not, see <http://www.gnu.org/licenses/>.
19 ////////////////////////////////////////////////////////////////////////////////////////
25 #include "stringoper.h"
30 * 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.
34 list<string> transitions;
37 string outputFilename;
38 string name_of_machine;
39 string name_of_first_state;
43 /** This function finds place in the transition table to put a transition there. */
44 int find_place(string model, int type)
48 for(int i = 3;i<cols;i++)
50 if(model.compare(0,model.size(),table[i])==0) return i;
55 for(int i = 1;i<rows;i++)
56 if(model.compare(0,model.size(),table[i*cols+2])==0) return i;
62 IO_operations( const string outputFile, const string FSM_name, const string firstState, const list<string> trans, const list<string> state, const list<string> ev )
64 outputFilename = outputFile;
65 name_of_machine = FSM_name;
66 name_of_first_state = firstState;
76 void setEvents(list<string> events) /** Set list of events to an attribute */
78 this->events = events;
81 void setTransitions(list<string> transitions) /** Set list of transitions to an attribute */
83 this->transitions = transitions;
86 void setStates(list<string> states) /** Set list of states to an attribute */
88 this->states = states;
91 void setNameOfStateMachine(string name_of_FSM) /** Set name of FSM to an attribute */
93 name_of_machine = name_of_FSM;
96 void setNameOfFirstState(string first_state) /** Set name of start state to an attribute */
98 name_of_first_state = first_state;
101 void setOutputFilename(string outputFilename) /** Set name of an output file to an attribute */
103 this->outputFilename = outputFilename;
106 void write_states(ofstream& filestr) /** This method write states to the output file and also to transition table. */
108 int pos1, pos2, cnt, subs;
110 string context, state, ctx, sState, str;
111 list<string> nstates = states;
112 context = name_of_machine;
114 table[1] = "Context";
116 for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++) // write all states in the context of the automaton
119 cnt = count(state,',');
122 pos1 = state.find(",");
123 ctx = cut_namespaces(state.substr(pos1+1));
124 if(ctx.compare(0,context.length(),context)==0)
126 str = cut_namespaces(state.substr(0,pos1));
128 table[cols*nState+2] = str;
129 table[cols*nState+1] = context;
133 if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
138 pos1 = state.find(",");
139 pos2 = state.rfind(",");
140 ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
141 if(ctx.compare(0,context.length(),context)==0)
143 str = cut_namespaces(state.substr(0,pos1));
145 table[cols*nState+2] = str;
146 table[cols*nState+1] = context;
148 if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
152 filestr<<name_of_first_state<<" [peripheries=2] ;\n";
154 while(!nstates.empty()) // substates ?
156 state = nstates.front();
157 filestr<<"subgraph cluster"<<subs<<" {\n";
158 pos1 = state.find(",");
159 pos2 = state.rfind(",");
160 context = cut_namespaces(state.substr(0,pos1));
161 filestr<<"label=\""<<context<<"\";\n";
162 sState = cut_namespaces(state.substr(pos2+1));
163 filestr<<sState<<" [peripheries=2] ;\n";
165 for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++)
168 cnt = count(state,',');
171 pos1 = state.find(",");
172 ctx = cut_namespaces(state.substr(pos1+1));
173 if(ctx.compare(0,context.length(),context)==0)
175 str = cut_namespaces(state.substr(0,pos1));
177 table[cols*nState+2] = str;
178 table[cols*nState+1] = context;
182 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
187 pos1 = state.find(",");
188 pos2 = state.rfind(",");
189 ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
190 if(ctx.compare(0,context.length(),context)==0)
192 str = cut_namespaces(state.substr(0,pos1));
194 table[cols*nState+2] = str;
195 table[cols*nState+1] = context;
197 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
207 void write_transitions(ofstream& filestr) /** Write transitions to the output file nad the transition table. */
210 string params, state, event, dest;
211 for(list<string>::iterator i = transitions.begin();i!=transitions.end();i++) // write all transitions
214 pos1 = params.find(",");
215 state = cut_namespaces(params.substr(0,pos1));
216 filestr<<state<<"->";
217 pos2 = params.rfind(",");
218 dest = cut_namespaces(params.substr(pos2+1));
220 event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
221 filestr<<"[label=\""<<event<<"\"];\n";
222 table[find_place(state,2)*cols+find_place(event,1)]=dest;
227 void fill_table_with_events() /** Fill the first row of the transition table with events. */
230 for(list<string>::iterator i = events.begin();i!=events.end();i++)
237 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. */
239 if(!name_of_first_state.empty())
241 ofstream filestr(outputFilename.c_str());
242 filestr<<"digraph "<< name_of_machine<< " {\n";
243 cols = events.size()+3;
244 rows = states.size()+1;
245 table = new string [cols*rows];
246 fill_table_with_events();
247 write_states(filestr);
248 write_transitions(filestr);
253 else cout<<"No state machine was found. So no output file was created.\n";
257 void print_table() /** This function prints the transition table. At first it counts the size of all columns. */
259 cout<<"\nTRANSITION TABLE\n";
260 unsigned * len = new unsigned[cols];
262 string line = "-|---|-";
263 for(int i = 1; i<cols; i++)
266 for(int j = 0;j<rows;j++)
268 if(len[i]<table[j*cols+i].length()) len[i] = table[j*cols+i].length();
270 for(unsigned k = 0; k<len[i]; k++)
277 for(int i = 0; i<rows; i++)
280 for(int j = 0;j<cols;j++)
283 cout<<left<<table[i*cols+j]<<" | ";
291 void print_stats() /** Print short statistics about the state machine */
293 cout<<"\n"<<"Statistics: \n";
294 cout<<"Number of states: "<<states.size()<<"\n";
295 cout<<"Number of events: "<<events.size()<<"\n";
296 cout<<"Number of transitions: "<<transitions.size()<<"\n\n";