OpenWalnut 1.3.1
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <fstream> 00027 #include <string> 00028 #include <vector> 00029 #include <iterator> 00030 00031 #include <boost/regex.hpp> 00032 00033 #include "WKernel.h" 00034 #include "combiner/WModuleProjectFileCombiner.h" 00035 #include "WRoiProjectFileIO.h" 00036 #include "../graphicsEngine/WGEProjectFileIO.h" 00037 #include "../common/exceptions/WFileNotFound.h" 00038 #include "../common/exceptions/WFileOpenFailed.h" 00039 #include "../common/WStringUtils.h" 00040 00041 #include "WProjectFile.h" 00042 00043 WProjectFile::WProjectFile( boost::filesystem::path project ): 00044 WThreadedRunner(), 00045 boost::enable_shared_from_this< WProjectFile >(), 00046 m_project( project ) 00047 { 00048 // initialize members 00049 00050 // The module graph parser 00051 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ) ); 00052 00053 // The ROI parser 00054 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ) ); 00055 00056 // The Camera parser 00057 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) ); 00058 } 00059 00060 WProjectFile::WProjectFile( boost::filesystem::path project, ProjectLoadCallback doneCallback ): 00061 WThreadedRunner(), 00062 boost::enable_shared_from_this< WProjectFile >(), 00063 m_project( project ), 00064 m_signalLoadDoneConnection( m_signalLoadDone.connect( doneCallback ) ) 00065 { 00066 // The module graph parser 00067 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ) ); 00068 00069 // The ROI parser 00070 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ) ); 00071 00072 // The Camera parser 00073 m_parsers.push_back( boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ) ); 00074 } 00075 00076 WProjectFile::~WProjectFile() 00077 { 00078 // cleanup 00079 m_parsers.clear(); 00080 m_signalLoadDoneConnection.disconnect(); 00081 } 00082 00083 boost::shared_ptr< WProjectFileIO > WProjectFile::getCameraWriter() 00084 { 00085 return boost::shared_ptr< WProjectFileIO >( new WGEProjectFileIO() ); 00086 } 00087 00088 boost::shared_ptr< WProjectFileIO > WProjectFile::getModuleWriter() 00089 { 00090 return boost::shared_ptr< WProjectFileIO >( new WModuleProjectFileCombiner() ); 00091 } 00092 00093 boost::shared_ptr< WProjectFileIO > WProjectFile::getROIWriter() 00094 { 00095 return boost::shared_ptr< WProjectFileIO >( new WRoiProjectFileIO() ); 00096 } 00097 00098 void WProjectFile::load() 00099 { 00100 // the instance needs to be added here, as it else could be freed before the thread finishes ( remember: it is a shared_ptr ). 00101 WKernel::getRunningKernel()->getRootContainer()->addPendingThread( shared_from_this() ); 00102 00103 // actually run 00104 run(); 00105 } 00106 00107 void WProjectFile::save( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer ) 00108 { 00109 wlog::info( "Project File" ) << "Saving project file \"" << m_project.string() << "\"."; 00110 00111 // open the file for write 00112 std::ofstream output( m_project.string().c_str() ); 00113 if( !output.is_open() ) 00114 { 00115 throw WFileOpenFailed( std::string( "The project file \"" ) + m_project.string() + 00116 std::string( "\" could not be opened for write access." ) ); 00117 } 00118 00119 // allow each parser to handle save request 00120 for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = writer.begin(); iter != writer.end(); ++iter ) 00121 { 00122 ( *iter )->save( output ); 00123 output << std::endl; 00124 } 00125 00126 output.close(); 00127 } 00128 00129 void WProjectFile::save() 00130 { 00131 save( m_parsers ); 00132 } 00133 00134 void WProjectFile::threadMain() 00135 { 00136 // Parse the file 00137 wlog::info( "Project File" ) << "Loading project file \"" << m_project.string() << "\"."; 00138 00139 // store some errors 00140 std::vector< std::string > errors; 00141 00142 // read the file 00143 std::ifstream input( m_project.string().c_str() ); 00144 if( !input.is_open() ) 00145 { 00146 errors.push_back( std::string( "The project file \"" ) + m_project.string() + std::string( "\" does not exist." ) ); 00147 00148 // give some feedback 00149 m_signalLoadDone( m_project, errors ); 00150 m_signalLoadDoneConnection.disconnect(); 00151 00152 // also throw an exception 00153 throw WFileNotFound( *errors.begin() ); 00154 } 00155 00156 // the comment 00157 static const boost::regex commentRe( "^ *//.*$" ); 00158 00159 // read it line by line 00160 std::string line; // the current line 00161 int i = 0; // line counter 00162 bool match = false; // true of a parser successfully parsed the line 00163 boost::smatch matches; // the list of matches 00164 00165 while( std::getline( input, line ) ) 00166 { 00167 ++i; // line number 00168 match = false; 00169 00170 // allow each parser to handle the line. 00171 for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter ) 00172 { 00173 try 00174 { 00175 if( ( *iter )->parse( line, i ) ) 00176 { 00177 match = true; 00178 // the first parser matching this line -> next line 00179 break; 00180 } 00181 } 00182 catch( const std::exception& e ) 00183 { 00184 errors.push_back( "Parse error on line " + string_utils::toString( i ) + ": " + e.what() ); 00185 wlog::error( "Project Loader" ) << errors.back(); 00186 } 00187 } 00188 00189 // did someone match this line? Or is it empty or a comment? 00190 if( !match && !line.empty() && !boost::regex_match( line, matches, commentRe ) ) 00191 { 00192 // no it is something else -> warning! Not a critical error. 00193 wlog::warn( "Project Loader" ) << "Line " << i << ": Malformed. Skipping."; 00194 } 00195 } 00196 00197 input.close(); 00198 00199 // finally, let every one know that we have finished 00200 for( std::vector< boost::shared_ptr< WProjectFileIO > >::const_iterator iter = m_parsers.begin(); iter != m_parsers.end(); ++iter ) 00201 { 00202 try 00203 { 00204 ( *iter )->done(); 00205 // append errors 00206 std::copy( ( *iter )->getErrors().begin(), ( *iter )->getErrors().end(), std::back_inserter( errors ) ); 00207 } 00208 catch( const std::exception& e ) 00209 { 00210 errors.push_back( "Exception while applying settings: " + std::string( e.what() ) ); 00211 wlog::error( "Project Loader" ) << errors.back(); 00212 } 00213 } 00214 00215 // give some feedback 00216 m_signalLoadDone( m_project, errors ); 00217 m_signalLoadDoneConnection.disconnect(); 00218 00219 // remove from thread list 00220 WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() ); 00221 } 00222 00223 void WProjectFile::onThreadException( const WException& e ) 00224 { 00225 // let WThreadedRunner do the remaining tasks. 00226 handleDeadlyException( e, "Project Loader" ); 00227 00228 // remove from thread list. Please note: this NEEDS to be done after handleDeadlyException - if done before, the thread pointer might be 00229 // deleted already. 00230 WKernel::getRunningKernel()->getRootContainer()->finishedPendingThread( shared_from_this() ); 00231 }