00001 #ifndef _ots_ConfigurationView_h_
00002 #define _ots_ConfigurationView_h_
00003
00004 #include "otsdaq-core/ConfigurationDataFormats/ViewColumnInfo.h"
00005 #include "otsdaq-core/MessageFacility/MessageFacility.h"
00006 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
00007 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationVersion.h"
00008
00009
00010 #include <string>
00011 #include <typeinfo>
00012 #include <iostream>
00013 #include <sstream>
00014 #include <vector>
00015 #include <cassert>
00016 #include <stdlib.h>
00017
00018 std::string ots_demangle(const char* name);
00019
00020 namespace ots
00021 {
00022
00023 class ConfigurationView
00024 {
00025
00026 public:
00027
00028 static const unsigned int INVALID;
00029 typedef std::vector<std::vector<std::string> > DataView;
00030 typedef DataView::iterator iterator;
00031 typedef DataView::const_iterator const_iterator;
00032
00033 ConfigurationView (const std::string &name="");
00034 virtual ~ConfigurationView (void);
00035 ConfigurationView& copy (const ConfigurationView &src, ConfigurationVersion destinationVersion, const std::string &author);
00036
00037
00038 void init(void);
00039
00040
00041
00042
00043 template<class T>
00044 unsigned int findRow(unsigned int col, const T& value,
00045 unsigned int offsetRow=0) const
00046 {
00047 std::istringstream s(value);
00048 return findRow(col,s.str(),offsetRow);
00049 }
00050 unsigned int findRow (unsigned int col, const std::string& value, unsigned int offsetRow=0) const;
00051
00052 template<class T>
00053 unsigned int findRowInGroup(unsigned int col, const T& value,
00054 const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow=0) const
00055 {
00056 std::istringstream s(value);
00057 return findRowInGroup(col,s.str(),groupId,childLinkIndex,offsetRow);
00058 }
00059 unsigned int findRowInGroup (unsigned int col, const std::string &value, const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow=0) const;
00060 unsigned int findCol (const std::string &name) const;
00061 unsigned int findColByType (const std::string &type, int startingCol = 0) const;
00062
00063
00064 const std::string& getUniqueStorageIdentifier (void) const;
00065 const std::string& getTableName (void) const;
00066 const ConfigurationVersion& getVersion (void) const;
00067 const std::string& getComment (void) const;
00068 const std::string& getAuthor (void) const;
00069 const time_t& getCreationTime (void) const;
00070 const time_t& getLastAccessTime (void) const;
00071 const bool& getLooseColumnMatching (void) const;
00072 const unsigned int getSourceColumnSize (void) const;
00073 const unsigned int& getSourceColumnMismatch (void) const;
00074 const unsigned int& getSourceColumnMissing (void) const;
00075 const std::set<std::string>& getSourceColumnNames (void) const;
00076 std::set<std::string> getColumnNames (void) const;
00077 std::set<std::string> getColumnStorageNames (void) const;
00078 std::vector<std::string> getDefaultRowValues (void) const;
00079
00080 unsigned int getNumberOfRows (void) const;
00081 unsigned int getNumberOfColumns (void) const;
00082 const unsigned int getColUID (void) const;
00083
00084
00085
00086
00087 private:
00088 bool isEntryInGroupCol (const unsigned int &row, const unsigned int &groupCol, const std::string &groupNeedle, std::set<std::string> *groupIDList = 0) const;
00089 public:
00090
00091 std::set<std::string> getSetOfGroupIDs (const std::string &childLinkIndex, unsigned int row = -1) const;
00092 bool isEntryInGroup (const unsigned int &row, const std::string &childLinkIndex, const std::string &groupNeedle) const;
00093 const bool getChildLink (const unsigned int &col, bool *isGroup, std::pair<unsigned int /*link col*/, unsigned int /*link id col*/> *linkPair) const;
00094 const unsigned int getColLinkGroupID (const std::string &childLinkIndex) const;
00095 void addRowToGroup (const unsigned int &row, const unsigned int &col, const std::string &groupID, const std::string &colDefault);
00096 void removeRowFromGroup (const unsigned int &row, const unsigned int &col, const std::string &groupID);
00097
00098
00099
00100
00101
00102 template<class T>
00103 void getValue(T& value, unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
00104 {
00105 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00106 throw std::runtime_error("Invalid row col requested");
00107
00108 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
00109 {
00110 std::string data = convertEnvironmentVariables?convertEnvVariables(theDataView_[row][col]):
00111 theDataView_[row][col];
00112
00113 if(!isNumber(data))
00114 {
00115 __SS__ << (data + " is not a number!") << std::endl;
00116 __MOUT__ << "\n" << ss.str();
00117 throw std::runtime_error(ss.str());
00118 }
00119
00120 if(typeid(double) == typeid(value))
00121 value = strtod(data.c_str(),0);
00122 else if(typeid(float) == typeid(value))
00123 value = strtof(data.c_str(),0);
00124 else if(data.size() > 2 && data[1] == 'x')
00125 value = strtol(data.c_str(),0,16);
00126 else if(data.size() > 1 && data[0] == 'b')
00127 value = strtol(data.substr(1).c_str(),0,2);
00128 else
00129 value = strtol(data.c_str(),0,10);
00130 }
00131 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
00132 columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING &&
00133 (typeid(int) == typeid(value) ||
00134 typeid(unsigned int) == typeid(value)))
00135 {
00136
00137
00138
00139
00140
00141 if(theDataView_[row][col] == ViewColumnInfo::DATATYPE_STRING_DEFAULT)
00142 value = 0;
00143 else
00144 {
00145 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
00146 for(value=1;value-1<(T)choices.size();++value)
00147 if(theDataView_[row][col] == choices[value-1])
00148 return;
00149
00150 __SS__ << "\tInvalid value for column data type: " << columnsInfo_[col].getDataType()
00151 << " in configuration " << tableName_
00152 << " at column=" << columnsInfo_[col].getName()
00153 << " for getValue with type '" << ots_demangle(typeid(value).name())
00154 << ".'"
00155 << "Attempting to get index of '" << theDataView_[row][col]
00156 << " in fixed choice array, but was not found in array. "
00157 << "Here are the valid choices:\n";
00158 ss << "\t" << ViewColumnInfo::DATATYPE_STRING_DEFAULT << "\n";
00159 for(const auto &choice:choices)
00160 ss << "\t" << choice << "\n";
00161 __MOUT__ << "\n" << ss.str();
00162 throw std::runtime_error(ss.str());
00163 }
00164 }
00165 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING &&
00166 typeid(bool) == typeid(value))
00167 {
00168 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
00169 value = (theDataView_[row][col] == ViewColumnInfo::TYPE_VALUE_ON) ? true:false;
00170 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
00171 value = (theDataView_[row][col] == ViewColumnInfo::TYPE_VALUE_TRUE) ? true:false;
00172 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
00173 value = (theDataView_[row][col] == ViewColumnInfo::TYPE_VALUE_YES) ? true:false;
00174 }
00175 else
00176 {
00177 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
00178 __MOUT_WARN__ << "For column type " << ViewColumnInfo::TYPE_FIXED_CHOICE_DATA
00179 << " the only valid numeric types are 'int' and 'unsigned int.'";
00180
00181 __SS__ << "\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
00182 << " and column type: " << columnsInfo_[col].getType()
00183 << ", in configuration " << tableName_
00184 << " at column=" << columnsInfo_[col].getName()
00185 << " for getValue with type '" << ots_demangle(typeid(value).name())
00186 << "'" << std::endl;
00187 throw std::runtime_error(ss.str());
00188 }
00189 }
00190 void getValue(std::string &value, unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00191 std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00192 std::string getEscapedValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00193 bool isURIEncodedCommentTheSame(const std::string &comment) const;
00194
00195 const DataView& getDataView (void) const;
00196 const std::vector<ViewColumnInfo>& getColumnsInfo (void) const;
00197 std::vector<ViewColumnInfo>* getColumnsInfoP(void);
00198 const ViewColumnInfo& getColumnInfo (unsigned int column) const;
00199
00200
00201
00202 void setUniqueStorageIdentifier (const std::string &storageUID);
00203 void setTableName (const std::string &name );
00204 void setComment (const std::string &comment );
00205 void setURIEncodedComment (const std::string &uriComment );
00206 void setAuthor (const std::string &author );
00207 void setCreationTime (time_t t );
00208 void setLastAccessTime (time_t t = time(0) );
00209 void setLooseColumnMatching (bool setValue );
00210
00211
00212 template<class T>
00213 void setVersion (const T &version)
00214 {
00215 version_ = ConfigurationVersion(version);
00216 }
00217
00218
00219
00220
00221 template<class T>
00222 void setValue(const T &value, unsigned int row, unsigned int col)
00223 {
00224 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00225 {
00226 __SS__ << "Invalid row (" << row << ") col (" << col << ") requested!" << std::endl;
00227 throw std::runtime_error(ss.str());
00228 }
00229
00230 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
00231 {
00232 std::stringstream ss;
00233 ss << value;
00234 theDataView_[row][col] = ss.str();
00235 }
00236 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME &&
00237 typeid(time_t) == typeid(value))
00238 {
00239
00240 std::stringstream ss;
00241 ss << value;
00242 theDataView_[row][col] = ss.str();
00243 }
00244 else
00245 {
00246 __SS__ << "\tUnrecognized view data type: " << columnsInfo_[col].getDataType()
00247 << " in configuration " << tableName_
00248 << " at column=" << columnsInfo_[col].getName()
00249 << " for setValue with type '" << ots_demangle(typeid(value).name())
00250 << "'" << std::endl;
00251 throw std::runtime_error(ss.str());
00252 }
00253 }
00254 void setValue (const std::string &value, unsigned int row, unsigned int col);
00255 void setValue (const char *value, unsigned int row, unsigned int col);
00256
00257
00258 void setValueAsString (const std::string &value, unsigned int row, unsigned int col);
00259
00260
00261 void resizeDataView (unsigned int nRows, unsigned int nCols);
00262 int addRow (void);
00263 void deleteRow (int r);
00264
00265
00266
00267
00268 iterator begin (void) {return theDataView_.begin();}
00269 iterator end (void) {return theDataView_.end();}
00270 const_iterator begin (void) const {return theDataView_.begin();}
00271 const_iterator end (void) const {return theDataView_.end();}
00272 void reset (void);
00273 void print (std::ostream &out = std::cout) const;
00274 void printJSON (std::ostream &out = std::cout) const;
00275 int fillFromJSON (const std::string &json);
00276 int fillFromCSV (const std::string &data, const int &dataOffset = 0, const std::string &author = "") throw(std::runtime_error);
00277 bool setURIEncodedValue (const std::string &value, const unsigned int &row, const unsigned int &col);
00278
00279 static std::string decodeURIComponent (const std::string& data);
00280
00281 private:
00282 const unsigned int getOrInitColUID (void);
00283
00284 ConfigurationView& operator= (const ConfigurationView src);
00285
00286
00287 std::string convertEnvVariables (const std::string& data) const;
00288 bool isNumber (const std::string& s) const;
00289
00290 std::string uniqueStorageIdentifier_;
00291 std::string tableName_ ;
00292 ConfigurationVersion version_ ;
00293 std::string comment_ ;
00294 std::string author_ ;
00295 time_t creationTime_ ;
00296 time_t lastAccessTime_ ;
00297 unsigned int colUID_ ;
00298 std::map<std::string, unsigned int> colLinkGroupIDs_;
00299
00300 bool fillWithLooseColumnMatching_;
00301 unsigned int sourceColumnMismatchCount_, sourceColumnMissingCount_;
00302 std::set<std::string> sourceColumnNames_;
00303
00304 std::vector<ViewColumnInfo> columnsInfo_ ;
00305 DataView theDataView_ ;
00306 };
00307 }
00308
00309
00310
00311 #endif