OpenWalnut  1.5.0dev
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 <iterator>
28 #include <list>
29 #include <memory>
30 #include <string>
31 #include <vector>
32 
33 #include <boost/regex.hpp>
34 
35 #include "../common/WStringUtils.h"
36 #include "../common/exceptions/WFileNotFound.h"
37 #include "../common/exceptions/WFileOpenFailed.h"
38 #include "../graphicsEngine/WGEProjectFileIO.h"
39 #include "WKernel.h"
40 #include "WModule.h"
41 #include "WProjectFile.h"
42 #include "WRoiProjectFileIO.h"
43 #include "combiner/WModuleProjectFileCombiner.h"
44 
46 
47 WProjectFile::WProjectFile( boost::filesystem::path project ):
49  std::enable_shared_from_this< WProjectFile >(),
50  m_project( project )
51 {
52  // initialize members
53  std::shared_ptr< WProjectFileIO > p1( new WModuleProjectFileCombiner() );
54  std::shared_ptr< WProjectFileIO > p2( new WRoiProjectFileIO() );
55  std::shared_ptr< WProjectFileIO > p3( new WGEProjectFileIO() );
56 
57  // The module graph parser
58  m_moduleIO = std::dynamic_pointer_cast< WModuleProjectFileCombiner >( p1->clone( this ) );
59  m_parsers.push_back( m_moduleIO );
60  m_writers.push_back( m_moduleIO );
61 
62  // The ROI parser
63  m_parsers.push_back( p2->clone( this ) );
64  m_writers.push_back( p2->clone( this ) );
65 
66  // The Camera parser
67  m_parsers.push_back( p3->clone( this ) );
68  m_writers.push_back( p3->clone( this ) );
69 
70  // add the current list of additional parsers
72 
73  // Grab all items and add to my own list of parsers
74  for( ParserList::ConstIterator it = r->get().begin(); it != r->get().end(); ++it )
75  {
76  if( ( *it )->getApplyOrder() == WProjectFileIO::POST_MODULES )
77  {
78  m_parsers.push_back( ( *it )->clone( this ) );
79  }
80  else
81  {
82  m_parsers.push_front( ( *it )->clone( this ) );
83  }
84 
85  // always add savers behind the module saver, to allow the module saver build the id map
86  m_writers.push_back( ( *it )->clone( this ) );
87  }
88 
89  // ticket unlocked automatically upon its destruction
90 }
91 
92 WProjectFile::WProjectFile( boost::filesystem::path project, ProjectLoadCallback doneCallback ):
94  std::enable_shared_from_this< WProjectFile >(),
95  m_project( project ),
96  m_signalLoadDoneConnection( m_signalLoadDone.connect( doneCallback ) )
97 {
98  // initialize members
99  std::shared_ptr< WProjectFileIO > p1( new WModuleProjectFileCombiner() );
100  std::shared_ptr< WProjectFileIO > p2( new WRoiProjectFileIO() );
101  std::shared_ptr< WProjectFileIO > p3( new WGEProjectFileIO() );
102 
103  // The module graph parser
104  m_moduleIO = std::dynamic_pointer_cast< WModuleProjectFileCombiner >( p1->clone( this ) );
105  m_parsers.push_back( m_moduleIO );
106  m_writers.push_back( m_moduleIO );
107 
108  // The ROI parser
109  m_parsers.push_back( p2->clone( this ) );
110  m_writers.push_back( p2->clone( this ) );
111 
112  // The Camera parser
113  m_parsers.push_back( p3->clone( this ) );
114  m_writers.push_back( p3->clone( this ) );
115 
116  // add the current list of additional parsers
118 
119  // Grab all items and add to my own list of parsers
120  for( ParserList::ConstIterator it = r->get().begin(); it != r->get().end(); ++it )
121  {
122  if( ( *it )->getApplyOrder() == WProjectFileIO::POST_MODULES )
123  {
124  m_parsers.push_back( ( *it )->clone( this ) );
125  }
126  else
127  {
128  m_parsers.push_front( ( *it )->clone( this ) );
129  }
130 
131  // always add savers behind the module saver, to allow the module saver build the id map
132  m_writers.push_back( ( *it )->clone( this ) );
133  }
134 
135  // ticket unlocked automatically upon its destruction
136 }
137 
139 {
140  // cleanup
141  m_parsers.clear();
142  m_writers.clear();
143  m_signalLoadDoneConnection.disconnect();
144 }
145 
146 std::shared_ptr< WProjectFileIO > WProjectFile::getCameraWriter()
147 {
148  return std::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() );
149 }
150 
151 std::shared_ptr< WProjectFileIO > WProjectFile::getModuleWriter()
152 {
153  return std::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() );
154 }
155 
156 std::shared_ptr< WProjectFileIO > WProjectFile::getROIWriter()
157 {
158  return std::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() );
159 }
160 
162 {
163  // the instance needs to be added here, as it else could be freed before the thread finishes ( remember: it is a shared_ptr ).
164  WKernel::getRunningKernel()->getRootContainer()->addPendingThread( shared_from_this() );
165 
166  // actually run
167  run();
168 }
169 
170 void WProjectFile::save( const std::vector< std::shared_ptr< WProjectFileIO > >& writer )
171 {
172  std::list< std::shared_ptr< WProjectFileIO > > l( writer.begin(), writer.end() );
173  save( l );
174 }
175 
176 void WProjectFile::save( const std::list< std::shared_ptr< WProjectFileIO > >& writer )
177 {
178  wlog::info( "Project File" ) << "Saving project file \"" << m_project.string() << "\".";
179 
180  // open the file for write
181  std::ofstream output( m_project.string().c_str() );
182  if( !output.is_open() )
183  {
184  throw WFileOpenFailed( std::string( "The project file \"" ) + m_project.string() +
185  std::string( "\" could not be opened for write access." ) );
186  }
187 
188  // allow each parser to handle save request
189  for( std::list< std::shared_ptr< WProjectFileIO > >::const_iterator iter = writer.begin(); iter != writer.end(); ++iter )
190  {
191  ( *iter )->save( output );
192  output << std::endl;
193  }
194 
195  output.close();
196 }
197 
199 {
200  save( m_writers );
201 }
202 
204 {
205  // Parse the file
206  wlog::info( "Project File" ) << "Loading project file \"" << m_project.string() << "\".";
207 
208  // store some errors and warnings
209  std::vector< std::string > errors;
210  std::vector< std::string > warnings;
211 
212  // read the file
213  std::ifstream input( m_project.string().c_str() );
214  if( !input.is_open() )
215  {
216  errors.push_back( std::string( "The project file \"" ) + m_project.string() + std::string( "\" does not exist." ) );
217 
218  // give some feedback
219  m_signalLoadDone( m_project, errors, warnings );
220  m_signalLoadDoneConnection.disconnect();
221 
222  // also throw an exception
223  throw WFileNotFound( *errors.begin() );
224  }
225 
226  // the comment
227  static const boost::regex commentRe( "^ *//.*$" );
228 
229  // read it line by line
230  std::string line; // the current line
231  int i = 0; // line counter
232  bool match = false; // true of a parser successfully parsed the line
233  boost::smatch matches; // the list of matches
234 
235  while( std::getline( input, line ) )
236  {
237  ++i; // line number
238  match = false;
239 
240  // allow each parser to handle the line.
241  for( std::list< std::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter )
242  {
243  try
244  {
245  if( ( *iter )->parse( line, i ) )
246  {
247  match = true;
248  // the first parser matching this line -> next line
249  break;
250  }
251  }
252  catch( const std::exception& e )
253  {
254  errors.push_back( "Parse error on line " + string_utils::toString( i ) + ": " + e.what() );
255  wlog::error( "Project Loader" ) << errors.back();
256  }
257  }
258 
259  // did someone match this line? Or is it empty or a comment?
260  if( !match && !line.empty() && !boost::regex_match( line, matches, commentRe ) )
261  {
262  // no it is something else -> warning! Not a critical error.
263  wlog::warn( "Project Loader" ) << "Line " << i << ": Malformed. Skipping.";
264  }
265  }
266 
267  input.close();
268 
269  // finally, let every one know that we have finished
270  for( std::list< std::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter )
271  {
272  try
273  {
274  ( *iter )->done();
275  // append errors and warnings
276  std::copy( ( *iter )->getErrors().begin(), ( *iter )->getErrors().end(), std::back_inserter( errors ) );
277  std::copy( ( *iter )->getWarnings().begin(), ( *iter )->getWarnings().end(), std::back_inserter( warnings ) );
278  }
279  catch( const std::exception& e )
280  {
281  errors.push_back( "Exception while applying settings: " + std::string( e.what() ) );
282  wlog::error( "Project Loader" ) << errors.back();
283  }
284  }
285 
286  // give some feedback
287  m_signalLoadDone( m_project, errors, warnings );
288  m_signalLoadDoneConnection.disconnect();
289 
290  // remove from thread list
291  WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() );
292 }
293 
295 {
296  // let WThreadedRunner do the remaining tasks.
297  handleDeadlyException( e, "Project Loader" );
298 
299  // remove from thread list. Please note: this NEEDS to be done after handleDeadlyException - if done before, the thread pointer might be
300  // deleted already.
301  WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() );
302 }
303 
305 {
307 
308  // find item if still inside
309  ParserList::Iterator it = std::find( w->get().begin(), w->get().end(), parser );
310  // item not inside? Add!
311  if( it == w->get().end() )
312  {
313  // add
314  w->get().push_back( parser );
315  }
316  // ticket unlocked automatically upon its destruction
317 }
318 
320 {
321  m_additionalParsers.remove( parser );
322 }
323 
324 std::shared_ptr< WModule > WProjectFile::mapToModule( unsigned int id ) const
325 {
326  return m_moduleIO->mapToModule( id );
327 }
328 
329 unsigned int WProjectFile::mapFromModule( std::shared_ptr< WModule > module ) const
330 {
331  return m_moduleIO->mapFromModule( module );
332 }
333 
Basic exception handler.
Definition: WException.h:39
Thrown whenever a file was not found.
Definition: WFileNotFound.h:37
Thrown whenever a file could not be opened.
IO class for writing the graphics engine state to a project file.
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WModuleContainer > getRootContainer() const
Returns the root module container.
Definition: WKernel.cpp:127
This class is able to parse project files and create the appropriate module graph inside a specified ...
std::shared_ptr< WProjectFileIO > SPtr
Abbreviation for a shared pointer.
Class loading project files.
Definition: WProjectFile.h:50
std::list< std::shared_ptr< WProjectFileIO > > m_writers
The writer instances.
Definition: WProjectFile.h:198
static ParserList m_additionalParsers
List of all additional parser prototypes.
Definition: WProjectFile.h:227
virtual ~WProjectFile()
Destructor.
boost::filesystem::path m_project
The project file to parse.
Definition: WProjectFile.h:188
ProjectLoadCallbackSignal m_signalLoadDone
Signal used to callback someone that the loader was finished.
Definition: WProjectFile.h:216
static void deregisterParser(WProjectFileIO::SPtr parser)
Remove parser from registry.
virtual void load()
Parses the project file and applies it.
boost::function< void(boost::filesystem::path, std::vector< std::string >, std::vector< std::string >) > ProjectLoadCallback
A callback function type reporting bach a finished load job.
Definition: WProjectFile.h:65
virtual void threadMain()
Function that has to be overwritten for execution.
boost::signals2::connection m_signalLoadDoneConnection
Connection managing the signal m_signalLoadDone.
Definition: WProjectFile.h:222
static std::shared_ptr< WProjectFileIO > getModuleWriter()
Returns an instance of the module writer.
virtual void onThreadException(const WException &e)
Do custom exception handling.
virtual void save()
Saves the current state to the file specified in the constructor.
std::list< std::shared_ptr< WProjectFileIO > > m_parsers
The parser instances.
Definition: WProjectFile.h:193
std::shared_ptr< WModuleProjectFileCombiner > m_moduleIO
This is the only WProjectFileIO instance which is needed.
Definition: WProjectFile.h:232
static void registerParser(WProjectFileIO::SPtr parser)
Register a custom project file parser.
WProjectFile(boost::filesystem::path project)
Default constructor.
static std::shared_ptr< WProjectFileIO > getROIWriter()
Returns an instance of the ROI writer.
std::shared_ptr< WModule > mapToModule(unsigned int id) const
Map a given project file ID to a module.
unsigned int mapFromModule(std::shared_ptr< WModule > module) const
Map a given module to project file ID.
static std::shared_ptr< WProjectFileIO > getCameraWriter()
Returns an instance of the Camera writer.
IO Class for writing the ROI structure to a project file.
std::shared_ptr< WSharedObjectTicketRead< S > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
std::shared_ptr< WSharedObjectTicketWrite< S > > WriteTicket
Type for write tickets.
Definition: WSharedObject.h:70
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
This class provides a common interface for thread-safe access to sequence containers (list,...
void remove(const typename S::value_type &element)
Searches and removes the specified element.
S::iterator Iterator
A typedef for the correct iterator to traverse this sequence container.
S::const_iterator ConstIterator
A typedef for the correct const iterator useful to traverse this sequence container.
Base class for all classes needing to be executed in a separate thread.
virtual void run()
Run thread.
void handleDeadlyException(const WException &e, std::string sender="WThreadedRunner")
Handle the specified exception which was not caught in the thread, which basically means the thread h...
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120
WStreamedLogger warn(const std::string &source)
Logging a warning message.
Definition: WLogger.h:309
WStreamedLogger info(const std::string &source)
Logging an information message.
Definition: WLogger.h:320
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:298