OpenWalnut  1.3.1
WProjectFile.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <fstream>
27 #include <string>
28 #include <vector>
29 #include <iterator>
30 
31 #include <boost/regex.hpp>
32 
33 #include "WKernel.h"
34 #include "combiner/WModuleProjectFileCombiner.h"
35 #include "WRoiProjectFileIO.h"
36 #include "../graphicsEngine/WGEProjectFileIO.h"
37 #include "../common/exceptions/WFileNotFound.h"
38 #include "../common/exceptions/WFileOpenFailed.h"
39 #include "../common/WStringUtils.h"
40 
41 #include "WProjectFile.h"
42 
43 WProjectFile::WProjectFile( boost::filesystem::path project ):
45  boost::enable_shared_from_this< WProjectFile >(),
46  m_project( project )
47 {
48  // initialize members
49 
50  // The module graph parser
51  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ) );
52 
53  // The ROI parser
54  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ) );
55 
56  // The Camera parser
57  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) );
58 }
59 
60 WProjectFile::WProjectFile( boost::filesystem::path project, ProjectLoadCallback doneCallback ):
62  boost::enable_shared_from_this< WProjectFile >(),
63  m_project( project ),
64  m_signalLoadDoneConnection( m_signalLoadDone.connect( doneCallback ) )
65 {
66  // The module graph parser
67  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ) );
68 
69  // The ROI parser
70  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ) );
71 
72  // The Camera parser
73  m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) );
74 }
75 
77 {
78  // cleanup
79  m_parsers.clear();
80  m_signalLoadDoneConnection.disconnect();
81 }
82 
83 boost::shared_ptr< WProjectFileIO > WProjectFile::getCameraWriter()
84 {
85  return boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() );
86 }
87 
88 boost::shared_ptr< WProjectFileIO > WProjectFile::getModuleWriter()
89 {
90  return boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() );
91 }
92 
93 boost::shared_ptr< WProjectFileIO > WProjectFile::getROIWriter()
94 {
95  return boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() );
96 }
97 
99 {
100  // the instance needs to be added here, as it else could be freed before the thread finishes ( remember: it is a shared_ptr ).
101  WKernel::getRunningKernel()->getRootContainer()->addPendingThread( shared_from_this() );
102 
103  // actually run
104  run();
105 }
106 
107 void WProjectFile::save( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
108 {
109  wlog::info( "Project File" ) << "Saving project file \"" << m_project.string() << "\".";
110 
111  // open the file for write
112  std::ofstream output( m_project.string().c_str() );
113  if( !output.is_open() )
114  {
115  throw WFileOpenFailed( std::string( "The project file \"" ) + m_project.string() +
116  std::string( "\" could not be opened for write access." ) );
117  }
118 
119  // allow each parser to handle save request
120  for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = writer.begin(); iter != writer.end(); ++iter )
121  {
122  ( *iter )->save( output );
123  output << std::endl;
124  }
125 
126  output.close();
127 }
128 
130 {
131  save( m_parsers );
132 }
133 
135 {
136  // Parse the file
137  wlog::info( "Project File" ) << "Loading project file \"" << m_project.string() << "\".";
138 
139  // store some errors
140  std::vector< std::string > errors;
141 
142  // read the file
143  std::ifstream input( m_project.string().c_str() );
144  if( !input.is_open() )
145  {
146  errors.push_back( std::string( "The project file \"" ) + m_project.string() + std::string( "\" does not exist." ) );
147 
148  // give some feedback
149  m_signalLoadDone( m_project, errors );
150  m_signalLoadDoneConnection.disconnect();
151 
152  // also throw an exception
153  throw WFileNotFound( *errors.begin() );
154  }
155 
156  // the comment
157  static const boost::regex commentRe( "^ *//.*$" );
158 
159  // read it line by line
160  std::string line; // the current line
161  int i = 0; // line counter
162  bool match = false; // true of a parser successfully parsed the line
163  boost::smatch matches; // the list of matches
164 
165  while( std::getline( input, line ) )
166  {
167  ++i; // line number
168  match = false;
169 
170  // allow each parser to handle the line.
171  for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter )
172  {
173  try
174  {
175  if( ( *iter )->parse( line, i ) )
176  {
177  match = true;
178  // the first parser matching this line -> next line
179  break;
180  }
181  }
182  catch( const std::exception& e )
183  {
184  errors.push_back( "Parse error on line " + string_utils::toString( i ) + ": " + e.what() );
185  wlog::error( "Project Loader" ) << errors.back();
186  }
187  }
188 
189  // did someone match this line? Or is it empty or a comment?
190  if( !match && !line.empty() && !boost::regex_match( line, matches, commentRe ) )
191  {
192  // no it is something else -> warning! Not a critical error.
193  wlog::warn( "Project Loader" ) << "Line " << i << ": Malformed. Skipping.";
194  }
195  }
196 
197  input.close();
198 
199  // finally, let every one know that we have finished
200  for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter )
201  {
202  try
203  {
204  ( *iter )->done();
205  // append errors
206  std::copy( ( *iter )->getErrors().begin(), ( *iter )->getErrors().end(), std::back_inserter( errors ) );
207  }
208  catch( const std::exception& e )
209  {
210  errors.push_back( "Exception while applying settings: " + std::string( e.what() ) );
211  wlog::error( "Project Loader" ) << errors.back();
212  }
213  }
214 
215  // give some feedback
216  m_signalLoadDone( m_project, errors );
217  m_signalLoadDoneConnection.disconnect();
218 
219  // remove from thread list
220  WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() );
221 }
222 
224 {
225  // let WThreadedRunner do the remaining tasks.
226  handleDeadlyException( e, "Project Loader" );
227 
228  // remove from thread list. Please note: this NEEDS to be done after handleDeadlyException - if done before, the thread pointer might be
229  // deleted already.
230  WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() );
231 }