]> rtime.felk.cvut.cz Git - boost-statechart-viewer.git/blob - src/iooper.h
a8a891096a29918bef8b176e222b345aace933c1
[boost-statechart-viewer.git] / src / iooper.h
1
2 ////////////////////////////////////////////////////////////////////////////////////////  
3 //    
4 //    This file is part of Boost Statechart Viewer.
5 //
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.
10 //
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.
15 //
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/>.
18 //
19 ////////////////////////////////////////////////////////////////////////////////////////
20
21 #include <fstream>
22 #include <list>
23 #include <string>
24
25 #include "stringoper.h"
26
27 using namespace std;
28
29 /**
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.
31 */
32 class IO_operations
33 {
34         list<string> transitions;
35         list<string> states;
36         list<string> events;
37         string outputFilename;
38         string name_of_machine;
39         string name_of_first_state;
40         string *table;
41         int nState;
42         int cols, rows;
43         /** This function finds place in the transition table to put a transition there. */
44         int find_place(string model, int type)
45         {
46                 if(type == 1)
47                 {
48                         for(int i = 3;i<cols;i++)
49                         {
50                                 if(model.compare(0,model.size(),table[i])==0) return i;
51                         }
52                 }
53                 else 
54                 {
55                         for(int i = 1;i<rows;i++)
56                         if(model.compare(0,model.size(),table[i*cols+2])==0) return i;
57                 }
58                 return -1;
59         }
60         public:
61         IO_operations() {}
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 )
63         {
64                 outputFilename = outputFile;
65                 name_of_machine = FSM_name;
66                 name_of_first_state = firstState;
67                 transitions = trans;
68                 states = state;
69                 events = ev;
70         }
71         ~IO_operations()
72         {
73                 delete table;
74         }
75         
76         void setEvents(list<string> events) /** Set list of events to an attribute */
77         {
78                 this->events = events;
79         }
80         
81         void setTransitions(list<string> transitions) /** Set list of transitions to an attribute */
82         {
83                 this->transitions = transitions;
84         }
85
86         void setStates(list<string> states) /** Set list of states to an attribute */
87         {
88                 this->states = states;
89         }
90
91         void setNameOfStateMachine(string name_of_FSM) /** Set name of FSM to an attribute */
92         {
93                 name_of_machine = name_of_FSM;
94         }
95
96         void setNameOfFirstState(string first_state) /** Set name of start state to an attribute */ 
97         {
98                 name_of_first_state = first_state;
99         }
100
101         void setOutputFilename(string outputFilename) /** Set name of an output file to an attribute */
102         {
103                 this->outputFilename = outputFilename;
104         }
105         
106         bool write_states(ofstream& filestr) /** This method write states to the output file and also to transition table. */
107         {
108                 int pos1, pos2, cnt, subs;
109                 nState = 1;
110                 string context, state, ctx, sState, str;
111                 list<string> nstates = states;
112                 context = name_of_machine;
113                 table[0] = "S";
114                 table[1] = "Context";
115                 table[2] = "State";
116                 for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++) // write all states in the context of the automaton
117                 {
118                         state = *i;
119                         cnt = count(state,',');
120                         if(cnt==1)
121                         {
122                                 pos1 = state.find(",");
123                                 ctx = cut_namespaces(state.substr(pos1+1));
124                                 if(ctx.compare(0,context.length(),context)==0)
125                                 {
126                                         str = cut_namespaces(state.substr(0,pos1));
127                                         filestr<<str<<";\n";
128                                         table[cols*nState+2] = str;
129                                         table[cols*nState+1] = context;
130                                         nState+=1;
131                                         nstates.erase(i);
132                                         i--;
133                                         if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
134                                 }
135                         }
136                         if(cnt==2)
137                         {
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)
142                                 {                               
143                                         str = cut_namespaces(state.substr(0,pos1));
144                                         filestr<<str<<";\n";
145                                         table[cols*nState+2] = str;
146                                         table[cols*nState+1] = context;                 
147                                         nState+=1;
148                                         if(str.compare(0,str.length(),name_of_first_state)==0) table[cols*(nState-1)] = "*";
149                                 }
150                         }
151                 }
152                 filestr<<name_of_first_state<<" [peripheries=2] ;\n";
153                 subs = 0;
154                 while(!nstates.empty()) // substates ?
155                 {
156                         state = nstates.front();
157                         filestr<<"subgraph cluster"<<subs<<" {\n";                      
158                         pos1 = state.find(",");
159                         pos2 = state.rfind(",");
160                         if(pos1 == pos2) return false;
161                                                 
162                         context = cut_namespaces(state.substr(0,pos1));
163                         filestr<<"label=\""<<context<<"\";\n";
164                         sState = cut_namespaces(state.substr(pos2+1));
165                         filestr<<sState<<" [peripheries=2] ;\n";        
166                         nstates.pop_front();    
167                         for(list<string>::iterator i = nstates.begin();i!=nstates.end();i++)
168                         {
169                                 state = *i;
170                                 cnt = count(state,',');
171                                 if(cnt==1)
172                                 {
173                                         pos1 = state.find(",");
174                                         ctx = cut_namespaces(state.substr(pos1+1));
175                                         if(ctx.compare(0,context.length(),context)==0)
176                                         {
177                                                 str = cut_namespaces(state.substr(0,pos1));
178                                                 filestr<<str<<";\n";
179                                                 table[cols*nState+2] = str;
180                                                 table[cols*nState+1] = context;
181                                                 nState+=1;
182                                                 nstates.erase(i);
183                                                 i--;
184                                                 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
185                                         }
186                                 }
187                                 if(cnt==2)
188                                 {
189                                         pos1 = state.find(",");
190                                         pos2 = state.rfind(",");
191                                         ctx = cut_namespaces(state.substr(pos1+1,pos2-pos1-1));
192                                         if(ctx.compare(0,context.length(),context)==0) 
193                                         {
194                                                 str = cut_namespaces(state.substr(0,pos1));
195                                                 filestr<<str<<";\n";
196                                                 table[cols*nState+2] = str;
197                                                 table[cols*nState+1] = context;
198                                                 nState+=1;
199                                                 if(str.compare(0,str.length(),sState)==0) table[cols*(nState-1)] = "*";
200                                         }
201                                 }
202                         }
203                         filestr<<"}\n";
204                         subs+=1;        
205                 }
206                 return true;
207         }
208
209         void write_transitions(ofstream& filestr) /** Write transitions to the output file nad the transition table. */
210         {
211                 int pos1, pos2;
212                 string params, state, event, dest;
213                 for(list<string>::iterator i = transitions.begin();i!=transitions.end();i++) // write all transitions
214                 {
215                         params = *i;
216                         pos1 = params.find(",");
217                         state = cut_namespaces(params.substr(0,pos1));
218                         filestr<<state<<"->";
219                         pos2 = params.rfind(",");
220                         dest = cut_namespaces(params.substr(pos2+1));
221                         filestr<<dest;
222                         event = cut_namespaces(params.substr(pos1+1,pos2-pos1-1));
223                         filestr<<"[label=\""<<event<<"\"];\n";
224                         table[find_place(state,2)*cols+find_place(event,1)]=dest;
225                 }               
226                 return;
227         }
228
229         void fill_table_with_events() /** Fill the first row of the transition table with events. */
230         {
231                 int j = 3;
232                 for(list<string>::iterator i = events.begin();i!=events.end();i++)
233                 {
234                         table[j] = *i;
235                         j++;
236                 }
237         }
238
239         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. */
240         {
241                 if(!name_of_first_state.empty())        
242                 {       
243                         ofstream filestr(outputFilename.c_str());
244                         filestr<<"digraph "<< name_of_machine<< " {\n";
245                         cols = events.size()+3;
246                         rows = states.size()+1;
247                         table = new string [cols*rows];
248                         fill_table_with_events();                       
249                         if(!write_states(filestr)) 
250                         {
251                                 cerr<<"Error during writing states.\n";
252                                 filestr<<"}";           
253                                 filestr.close();
254                                 return;                 
255                         }
256                         write_transitions(filestr);
257                         filestr<<"}";           
258                         filestr.close();
259                         print_table();
260                 }
261                 else cout<<"No state machine was found. So no output file was created.\n";
262                 return;
263         }
264
265         void print_table() /** This function prints the transition table. At first it counts the size of all columns. */
266         {
267                 cout<<"\nTRANSITION TABLE\n";
268                 unsigned * len = new unsigned[cols];
269                 len[0] = 1;
270                 string line = "-|---|-";
271                 for(int i = 1; i<cols; i++)
272                 {
273                         len[i] = 0;
274                         for(int j = 0;j<rows;j++)
275                         {
276                                 if(len[i]<table[j*cols+i].length()) len[i] = table[j*cols+i].length();
277                         }
278                         for(unsigned k = 0; k<len[i]; k++)
279                         {
280                                 line.append("-");
281                         }
282                         line.append("-|-");
283                 }
284                 cout<<line<<"\n";
285                 for(int i = 0; i<rows; i++)
286                 {
287                         cout<<" | ";            
288                         for(int j = 0;j<cols;j++)
289                         {
290                                 cout.width(len[j]);
291                                 cout<<left<<table[i*cols+j]<<" | ";
292                         }
293                         cout<<"\n";
294                         cout<<line<<"\n";
295                 }
296                 delete len;
297         }
298
299         void print_stats() /** Print short statistics about the state machine */
300         {
301                 cout<<"\n"<<"Statistics: \n";
302                 cout<<"Number of states: "<<states.size()<<"\n";
303                 cout<<"Number of events: "<<events.size()<<"\n";
304                 cout<<"Number of transitions: "<<transitions.size()<<"\n\n";
305                 return;
306         }
307
308 };