Confdump Agent  1.4.0
FixedTable.cpp
Go to the documentation of this file.
00001 /* 
00002  * Confdump-Agent - Dump static and runtime system configuration
00003  * Copyright (C) 2009-2012  Straton IT, SAS
00004  * 
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  * 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include <cctype>
00019 #include <cassert>
00020 #include <iostream>
00021 #include <stdexcept>
00022 #include <string>
00023 
00024 #include "boost/algorithm/string/trim.hpp"
00025 
00026 #include "QVariant"
00027 
00028 #include "Confdump/RuntimeError.hpp"
00029 #include "Confdump/System/FixedTable.hpp"
00030 #include "Confdump/System/ManagedElement.hpp"
00031 
00032 using std::vector;
00033 using std::map;
00034 using std::string;
00035 using std::getline;
00036 using boost::shared_ptr;
00037 using boost::algorithm::trim;
00038 
00039 namespace Confdump
00040 {
00041 
00042 namespace System
00043 {
00044 
00045 FixedTable::FixedTable()
00046 {
00047 }
00048 
00049 FixedTable::~FixedTable()
00050 {
00051 }
00052 
00053 void FixedTable::readHeaderFrom( QString headers)
00054 {
00055     //needs to be optimisated by converting each called function to use QString instead of std::String
00056     switch ( specification_.parsingMode() )
00057     {
00058     case UseSpecifiedHeaders:
00059         checkColumnPositionsFromSpecification( headers.toStdString() );
00060         break;
00061 
00062     case DetectWidthsFromHeader:
00063         detectColumnPositionsFromLine( headers.toStdString());
00064         break;
00065     }
00066 
00067     splitLineOnColumnPositions( headers.toStdString(), header_ );
00068 }
00069 
00070 bool FixedTable::readLineFrom( QString line, boost::shared_ptr<ManagedElement> row )
00071 {
00072 
00073     vector<string> lineData;
00074     splitLineOnColumnPositions( line.toStdString(), lineData );
00075     for ( unsigned i = 0; i < lineData.size(); ++i )
00076     {
00077         string translatedHeader;
00078         map<string, string>::iterator translation = fieldTranslations_.find( header_[i] );
00079         if ( translation != fieldTranslations_.end() )
00080             translatedHeader = translation->second;
00081         else
00082             translatedHeader = header_[i];
00083 
00084         QString unicodeData( QString::fromLocal8Bit( lineData[i].c_str() ) );
00085         row->setProperty( translatedHeader.c_str(), unicodeData );
00086     }
00087 
00088     return true;
00089 }
00090 
00091 void FixedTable::detectColumnPositionsFromLine( const std::string &line )
00092 {
00093     columnPositions_.clear();
00094 
00095     bool scanning = true;
00096     for ( string::size_type i = 0; i < line.size(); ++i )
00097     {
00098         if ( scanning ) // looking for the next column
00099         {
00100             if ( line[i] != ' ' )
00101             {
00102                 scanning = false;
00103                 columnPositions_.push_back( i );
00104             }
00105         }
00106         else // reading a column
00107         {
00108             if ( line[i] == ' ' )
00109             {
00110                 scanning = true;
00111             }
00112         }
00113     }
00114 
00115     // If the line was empty, consider it as a single column
00116     if ( columnPositions_.empty() )
00117         columnPositions_.push_back( 0 );
00118 
00119     // For the ease of later use, add a dummy EOL end position
00120     columnPositions_.push_back( line.size() );
00121 }
00122 
00123 void FixedTable::checkColumnPositionsFromSpecification( const std::string &line )
00124 {
00125     columnPositions_.clear();
00126 
00127     unsigned columnStart = 0;
00128     for ( Specification::ColumnHeadIterator head = specification_.columnHeadsBegin();
00129           head != specification_.columnHeadsEnd(); ++head )
00130     {
00131         if ( line.size() >= columnStart + head->skip + head->width ) // Size
00132         {
00133             string headerChunk = line.substr( columnStart + head->skip, head->width );
00134             trim( headerChunk );
00135 
00136             if ( headerChunk == head->name ) // Trimmed contents
00137             {
00138                 columnPositions_.push_back( columnStart + head->skip );
00139                 columnStart += head->skip + head->width;
00140             }
00141             else
00142             {
00143                 throw RuntimeError( QObject::tr( "Expected column head '%1', got '%2'" ).arg( QString::fromStdString( head->name ) ).arg( QString::fromStdString( headerChunk ) ) );
00144             }
00145         }
00146         else
00147         {
00148             throw RuntimeError( QObject::tr( "Reached unexpected end of header line while reading column head '%1'" ).arg( QString::fromStdString( head->name ) ) );
00149         }
00150     }
00151 
00152     // For the ease of later use, add a dummy EOL end position
00153     columnPositions_.push_back( line.size() );
00154 }
00155 
00156 void FixedTable::splitLineOnColumnPositions( const std::string &line, vector<string> &row )
00157 {
00158     for ( string::size_type i = 0; i < columnPositions_.size()-1; ++i )
00159     {
00160         string cell;
00161         if ( columnPositions_[i] < columnPositions_[i+1] - 1 )
00162         {
00163             cell = string(
00164                 line.c_str() + columnPositions_[i],
00165                 line.c_str() + columnPositions_[i+1] - 1 );
00166         }
00167         trim( cell );
00168         row.push_back( cell );
00169     }
00170 }
00171 
00172 void FixedTable::setSpecification( const Specification &spec )
00173 {
00174     specification_ = spec;
00175 }
00176 
00177 void FixedTable::setFieldTranslations( const std::map<string, string> &translations )
00178 {
00179     fieldTranslations_ = translations;
00180 }
00181 
00182 
00183 /*
00184  * FixedTable::Specification
00185  */
00186 
00187 FixedTable::Specification::Specification()
00188 {
00189 }
00190 
00191 FixedTable::Specification::~Specification()
00192 {
00193 }
00194 
00195 FixedTable::Specification& FixedTable::Specification::addColumnHead( const std::string &name, unsigned skip, unsigned width )
00196 {
00197     ColumnHead head;
00198     head.name = name;
00199     head.skip = skip;
00200     head.width = width;
00201 
00202     columnHeads_.push_back( head );
00203 
00204     return *this;
00205 }
00206 
00207 FixedTable::Specification::ColumnHeadIterator FixedTable::Specification::columnHeadsBegin() const
00208 {
00209     return columnHeads_.begin();
00210 }
00211 
00212 FixedTable::Specification::ColumnHeadIterator FixedTable::Specification::columnHeadsEnd() const
00213 {
00214     return columnHeads_.end();
00215 }
00216 
00217 }
00218 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends