Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

PatternManager.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Application                                               *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "PatternManager.h"
00025 #include "Debug.h"
00026 #include "Utilities.h"
00027 #include "PatternTypes.h"
00028 #include "GlobalVariables.h"
00029 
00030 //Qt includes
00031 #include <qstringlist.h>
00032 #include <qfile.h>
00033 
00034 //Other includes
00035 #include <iostream>
00036 using namespace std;
00037 using namespace mysqlpp;
00038 
00039 
00040 /*! Constructor. */
00041 PatternManager::PatternManager(DBInterface *pattDBInter){
00042         //Store reference to database
00043         patternDBInterface = pattDBInter;
00044 }
00045 
00046 
00047 /*! Destructor. */
00048 PatternManager::~ PatternManager(){
00049         #ifdef MEMORY_DEBUG
00050                 cout<<"DESTROYING PATTERN MANAGER"<<endl;
00051         #endif//MEMORY_DEBUG
00052 }
00053 
00054 
00055 //--------------------------------------------------------------------------------
00056 //----------------------------- PUBLIC METHODS -----------------------------------
00057 //--------------------------------------------------------------------------------
00058 
00059 /*! Loads test spiking patterns into database.
00060         These are specified as a qstringlist of absolute file locations. */
00061 bool PatternManager::addPattern(QString fileName){
00062         //Check filename is not too long
00063         if(fileName.length() > MAX_DATABASE_NAME_LENGTH){
00064                 cerr<<"PatternManager: FILENAME \""<<fileName<<"\" IS TOO LONG TO BE STORED IN DATABASE"<<endl;
00065                 return false;
00066         }
00067 
00068         //Create file with fileName
00069         QFile file(fileName);
00070         
00071         //Initialise variables for pattern
00072         unsigned int type = 0, width = 0, height = 0;
00073         QString description = "";
00074         int patternGrpID = -1, patternCount = 0;
00075 
00076         //Read in pattern
00077         if ( file.open( IO_ReadOnly ) ) {
00078                 QTextStream stream( &file );
00079                 QString fileLine;
00080 
00081                 while ( !stream.atEnd() ) {
00082                         fileLine = stream.readLine(); // line of text excluding '\n'
00083                         #ifdef LOAD_PATTERN_DEBUG
00084                                 cout<<"Reading line: \""<<fileLine<<"\""<<endl;
00085                         #endif//LOAD_PATTERN_DEBUG
00086 
00087                         //Extract information about pattern
00088                         if(fileLine.upper().startsWith("# TYPE:") || fileLine.upper().startsWith("#TYPE:") ){
00089                                 if(fileLine.section(": ", 1, 1) == "static")
00090                                         type = STATIC_PATTERN_VALUE;
00091                                 else if (fileLine.section(": ", 1, 1) == "temporal")
00092                                         type = TEMPORAL_PATTERN_VALUE;
00093                                 else{
00094                                         cerr<<"PatternManager: PATTERN TYPE NOT RECOGNIZED!"<<endl;
00095                                         return false;
00096                                 }
00097                         }
00098                         else if( fileLine.upper().startsWith("# WIDTH:") || fileLine.upper().startsWith("#WIDTH:") )
00099                                 width = Utilities::getUInt(fileLine.section(": ", 1, 1).ascii());
00100                         else if( fileLine.upper().startsWith("# HEIGHT:") || fileLine.upper().startsWith("#HEIGHT:") )
00101                                 height = Utilities::getUInt(fileLine.section(": ", 1, 1).ascii());
00102                         else if(fileLine.upper().startsWith("# DESCRIPTION:") || fileLine.upper().startsWith("#DESCRIPTION:") ){
00103                                 description = fileLine.section(": ", 1, 1);
00104                                 if(description.length() > MAX_DATABASE_NAME_LENGTH){
00105                                         cerr<<"PatternManager: DESCRIPTION \""<<description<<"\" IS TOO LONG TO BE STORED IN DATABASE"<<endl;
00106                                         return false;
00107                                 }
00108                         }
00109                         
00110                         //Store the pattern description and location
00111                         if(patternGrpID == -1 && type > 0 && width > 0 && height > 0 && description != ""){//All information about pattern has been found
00112                                 #ifdef LOAD_PATTERN_DEBUG
00113                                         cout<<"Storing pattern: "<<description<<" from "<<fileName<<endl;
00114                                 #endif//LOAD_PATTERN_DEBUG
00115 
00116                                 patternGrpID = storePatternDescription(description, type, width, height, fileName);
00117                                 if(patternGrpID == -1)//Pattern is already stored, assume that pattern data has been stored too.
00118                                         return true;
00119                                 else if(patternGrpID == -2)//Error during storing 
00120                                         return false;
00121                         }
00122                         
00123                         /* Store pattern data. Only do this if have successfully
00124                                 stored pattern description */
00125                         if(fileLine.upper().startsWith("# PATTERN DATA") || fileLine.upper().startsWith("#PATTERN DATA") ){
00126                                 if(patternGrpID > -1){
00127                                         QString patternLine = "";
00128                                         //Read in lines containing the pattern
00129                                         for(unsigned int i=0; i<height; ++i){
00130                                                 fileLine = stream.readLine();
00131                                                 QStringList numberList = QStringList::split(" ", fileLine);
00132                                                 fileLine = numberList.join(",");
00133                                                 fileLine += ",";
00134                                                 patternLine += fileLine;
00135                                         }
00136                                         //Trim the last comma
00137                                         patternLine.truncate(patternLine.length() - 1);
00138         
00139                                         //Write the pattern to the database
00140                                         storePatternData(patternGrpID, patternLine);
00141                                         ++patternCount;
00142                                 }
00143                                 else{//Pattern description has not been stored, but we have started reading in pattern data
00144                                         cerr<<"PatternManager: ERROR IN PATTERN FILE. HAVE NOT FOUND ONE OR MORE OF TYPE, WIDTH, HEIGHT, DESCRIPTION PRIOR TO START OF PATTERN DATA. FILENAME = "<<fileName<<endl;
00145                                         return false;
00146                                 }
00147                         }
00148                 }
00149                 //Store the number of loaded patterns
00150                 storePatternCount(patternGrpID, patternCount);
00151                 file.close();
00152         }
00153         else{
00154                 cerr<<"PatternManager: ERROR OPENING FILE "<<fileName<<endl;
00155                 return false;
00156         }
00157 
00158         //If we have reached this point without storing anything, something must have gone wrong with pattern loading
00159         if(patternGrpID == -1){
00160                 cerr<<"PatternManager: FAILED TO STORE PATTERN DESCRIPTION. PROBABLY AN ERROR IN THE PATTERN INPUT FILE"<<endl;
00161                 return false;
00162         }
00163         if(patternCount == 0){
00164                 cerr<<"PatternManager: EMPTY PATTERN. PROBABLY AN ERROR IN THE PATTERN INPUT FILE"<<endl;
00165                 return false;
00166         }
00167 
00168 
00169         //If we have reached this point everything should be ok.
00170         #ifdef LOAD_PATTERN_DEBUG
00171                 cout<<"Pattern loaded successfully from file \""<<fileName<<"\""<<endl;
00172         #endif//LOAD_PATTERN_DEBUG
00173         return true;
00174 }
00175 
00176 
00177 /*! Deletes the specified pattern from the database.
00178         NOTE Exception handling should be done by the invoking method. */
00179 bool PatternManager::deletePattern(unsigned int patternID){
00180         //Get query and create variable to record errors
00181         Query query = patternDBInterface->getQuery();
00182         bool deleteSuccess = true;
00183 
00184         //Delete description of pattern
00185         query.reset();
00186         query<<"DELETE FROM PatternDescriptions WHERE PatternGrpID = "<<patternID;
00187         ResNSel queryResult = query.execute();
00188         if(!queryResult.success){
00189                 cerr<<"PatternManager: FAILED TO DELETE PATTERN WITH ID"<<patternID<<" FROM PatternDescriptions"<<endl;
00190                 deleteSuccess = false;
00191         }
00192 
00193         //Delete pattern data
00194         query.reset();
00195         query<<"DELETE FROM PatternData WHERE PatternGrpID = "<<patternID;
00196         queryResult = query.execute();
00197         if(!queryResult.success){
00198                 cerr<<"PatternManager: FAILED TO DELETE PATTERN WITH ID"<<patternID<<" FROM PatternData"<<endl;
00199                 deleteSuccess = false;
00200         }
00201 
00202         //Return status
00203         return deleteSuccess;
00204 }
00205 
00206 
00207 //------------------------------------------------------------------------------------------------------
00208 //------------------------------------ PRIVATE METHODS -------------------------------------------------
00209 //------------------------------------------------------------------------------------------------------
00210 
00211 /*! Returns true if the pattern has already been stored in the database. */
00212 bool PatternManager::patternAlreadyStored(QString fileName){
00213         Result result;
00214         Query query = patternDBInterface->getQuery();
00215         query.reset();
00216         query<<"SELECT COUNT(*) FROM PatternDescriptions WHERE File = \""<<fileName<<"\"";
00217         try{
00218                 result = query.store();
00219         }
00220         catch(Exception ex){
00221                 cerr<<"PatternManager: EXCEPTION THROWN CHECKING IF PATTERN WAS STORED: "<<ex.what()<<endl;
00222                 return true;//Stops any further attempt to save pattern
00223         }
00224 
00225         //Check that query went ok
00226         if(result.size() < 1){
00227                 cerr<<"PatternManager: UNSUCCESSFUL SEARCH FOR PATTERN DESCRIPTION"<<endl;
00228                 return false;
00229         }
00230 
00231         //Extract count from result
00232         Row row(*result.begin());
00233         unsigned int numberOfRows = Utilities::getUInt((std::string)row["COUNT(*)"]);
00234         if(numberOfRows > 0)
00235                 return true;
00236         else{
00237                 return false;
00238         }
00239 }
00240 
00241 
00242 /*! Stores a count of the number of patterns in the database to save counting the
00243         number of rows every time the application starts up. */
00244 void PatternManager::storePatternCount(unsigned int patternGrpID, int patternCount){
00245         Query query = patternDBInterface->getQuery();
00246         query.reset();
00247         query<<"UPDATE PatternDescriptions SET NumberOfPatterns = "<<patternCount<<" WHERE PatternGrpID = "<<patternGrpID;
00248         ResNSel queryResult = query.execute();
00249         if(!queryResult.success){
00250                 cerr<<"PatternManager: UNSUCCESSFUL MYSQLPP QUERY STORING PATTERN DESCRIPTION"<<endl;
00251         }
00252 }
00253 
00254 
00255 /*! Stores the pattern data. */
00256 bool PatternManager::storePatternData(unsigned int patternGrpID, QString patternString){
00257         //Set up query
00258         Query patternQuery = patternDBInterface->getQuery();
00259         patternQuery.reset();
00260 
00261         //Set up string for writing
00262         string stemp (patternString.ascii(), patternString.length()) ;
00263         ostringstream strbuf;
00264         strbuf <<"INSERT INTO PatternData(PatternGrpID, Pattern) VALUES ( "<<patternGrpID<<", \""<<mysqlpp::escape<<stemp<<"\" )";
00265         try{
00266                 bool queryOk = patternQuery.exec(strbuf.str());
00267                 if(!queryOk){
00268                         cerr<<"PatternManager: UNSUCCESSFUL MYSQLPP QUERY: "<<strbuf.str()<<endl;
00269                         return false;
00270                 }
00271         }
00272         catch(Exception ex){
00273                 cerr<<"PatternManager: EXCEPTION THROWN BY UNSUCCESSFUL MYSQLPP QUERY: "<<strbuf.str()<<ex.what()<<endl;
00274                 return false;
00275         }
00276         return true;
00277 }
00278 
00279 
00280 /*! Stores a description of the pattern when the pattern is being loaded. Should be called
00281         before storing the data. */
00282 int PatternManager::storePatternDescription(QString description, unsigned short patternType, unsigned int width, unsigned int length, QString fileName){
00283         //First check to see if pattern is already stored
00284         if(patternAlreadyStored(fileName)){
00285                 #ifdef LOAD_PATTERN_DEBUG
00286                         cout<<"Pattern from file "<<fileName<<" is already stored."<<endl;
00287                 #endif//LOAD_PATTERN_DEBUG
00288                 return -1;//Don't want to store this pattern twice
00289         }
00290 
00291         Query query = patternDBInterface->getQuery();
00292         query.reset();
00293         query<<"INSERT INTO PatternDescriptions(Description, PatternType, Width, Length, File) VALUES ( \""<<description<<"\", "<<patternType<<", "<<width<<", "<<length<<",\""<<fileName<<"\")";
00294         ResNSel queryResult = query.execute();
00295         if(!queryResult.success){
00296                 cerr<<"PatternManager: UNSUCCESSFUL MYSQLPP QUERY STORING PATTERN DESCRIPTION"<<endl;
00297                 return -2;
00298         }
00299         else{
00300                 return queryResult.insert_id;
00301         }
00302 }
00303 
00304 
00305 

Generated on Mon Sep 3 22:29:04 2007 for SpikeStream Application by  doxygen 1.4.4