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