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 #include <time.h>
00018
00019 std::string ots_demangle(const char* name);
00020
00021 namespace ots
00022 {
00023
00024 class ConfigurationView
00025 {
00026
00027 public:
00028
00029 static const unsigned int INVALID;
00030 typedef std::vector<std::vector<std::string> > DataView;
00031 typedef DataView::iterator iterator;
00032 typedef DataView::const_iterator const_iterator;
00033
00034 ConfigurationView (const std::string &name="");
00035 virtual ~ConfigurationView (void);
00036 ConfigurationView& copy (const ConfigurationView &src, ConfigurationVersion destinationVersion, const std::string &author);
00037
00038
00039 void init(void);
00040
00041
00042
00043
00044 template<class T>
00045 unsigned int findRow(unsigned int col, const T& value,
00046 unsigned int offsetRow=0) const
00047 {
00048 std::istringstream s(value);
00049 return findRow(col,s.str(),offsetRow);
00050 }
00051 unsigned int findRow (unsigned int col, const std::string& value, unsigned int offsetRow=0) const;
00052
00053 template<class T>
00054 unsigned int findRowInGroup(unsigned int col, const T& value,
00055 const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow=0) const
00056 {
00057 std::istringstream s(value);
00058 return findRowInGroup(col,s.str(),groupId,childLinkIndex,offsetRow);
00059 }
00060 unsigned int findRowInGroup (unsigned int col, const std::string &value, const std::string &groupId, const std::string &childLinkIndex, unsigned int offsetRow=0) const;
00061 unsigned int findCol (const std::string &name) const;
00062 unsigned int findColByType (const std::string &type, int startingCol = 0) const;
00063
00064
00065 const std::string& getUniqueStorageIdentifier (void) const;
00066 const std::string& getTableName (void) const;
00067 const ConfigurationVersion& getVersion (void) const;
00068 const std::string& getComment (void) const;
00069 const std::string& getAuthor (void) const;
00070 const time_t& getCreationTime (void) const;
00071 const time_t& getLastAccessTime (void) const;
00072 const bool& getLooseColumnMatching (void) const;
00073 const unsigned int getDataColumnSize (void) const;
00074 const unsigned int& getSourceColumnMismatch (void) const;
00075 const unsigned int& getSourceColumnMissing (void) const;
00076 const std::set<std::string>& getSourceColumnNames (void) const;
00077 std::set<std::string> getColumnNames (void) const;
00078 std::set<std::string> getColumnStorageNames (void) const;
00079 std::vector<std::string> getDefaultRowValues (void) const;
00080
00081 unsigned int getNumberOfRows (void) const;
00082 unsigned int getNumberOfColumns (void) const;
00083 const unsigned int getColUID (void) const;
00084
00085
00086
00087
00088 private:
00089 bool isEntryInGroupCol (const unsigned int& row, const unsigned int& groupCol, const std::string& groupNeedle, std::set<std::string>* groupIDList = 0) const;
00090 public:
00091
00092 std::set<std::string> getSetOfGroupIDs (const std::string& childLinkIndex, unsigned int row = -1) const;
00093 bool isEntryInGroup (const unsigned int& row, const std::string& childLinkIndex, const std::string& groupNeedle) const;
00094 const bool getChildLink (const unsigned int& col, bool& isGroup, std::pair<unsigned int /*link col*/, unsigned int /*link id col*/>& linkPair) const;
00095 const unsigned int getColLinkGroupID (const std::string& childLinkIndex) const;
00096 void addRowToGroup (const unsigned int& row, const unsigned int& col, const std::string& groupID, const std::string& colDefault);
00097 void removeRowFromGroup (const unsigned int& row, const unsigned int& col, const std::string& groupID);
00098
00099
00100
00101
00102
00103 template<class T>
00104 void getValue(T& value, unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const
00105 {
00106 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00107 {
00108 __SS__ << "Invalid row col requested" << std::endl;
00109 __MOUT_ERR__ << "\n" << ss.str();
00110 throw std::runtime_error(ss.str());
00111 }
00112
00113 value = validateValueForColumn<T>(theDataView_[row][col],col,convertEnvironmentVariables);
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 }
00197
00198
00199 void getValue(std::string& value, unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00200
00201
00202
00203
00204
00205
00206
00207 template<class T>
00208 T validateValueForColumn(const std::string& value, unsigned int col,
00209 bool convertEnvironmentVariables=true) const
00210 {
00211 if(col >= columnsInfo_.size())
00212 {
00213 __SS__ << "Invalid col requested" << std::endl;
00214 __MOUT_ERR__ << "\n" << ss.str();
00215 throw std::runtime_error(ss.str());
00216 }
00217
00218 T retValue;
00219
00220 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
00221 {
00222 std::string data = convertEnvironmentVariables?convertEnvVariables(value):
00223 value;
00224
00225 if(!isNumber(data))
00226 {
00227 __SS__ << (data + " is not a number!") << std::endl;
00228 __MOUT__ << "\n" << ss.str();
00229 throw std::runtime_error(ss.str());
00230 }
00231
00232 if(typeid(double) == typeid(retValue))
00233 retValue = strtod(data.c_str(),0);
00234 else if(typeid(float) == typeid(retValue))
00235 retValue = strtof(data.c_str(),0);
00236 else if(data.size() > 2 && data[1] == 'x')
00237 retValue = strtol(data.c_str(),0,16);
00238 else if(data.size() > 1 && data[0] == 'b')
00239 retValue = strtol(data.substr(1).c_str(),0,2);
00240 else
00241 retValue = strtol(data.c_str(),0,10);
00242 }
00243 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA &&
00244 columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING &&
00245 (typeid(int) == typeid(retValue) ||
00246 typeid(unsigned int) == typeid(retValue)))
00247 {
00248
00249
00250
00251
00252
00253 if(value == ViewColumnInfo::DATATYPE_STRING_DEFAULT)
00254 retValue = 0;
00255 else
00256 {
00257 std::vector<std::string> choices = columnsInfo_[col].getDataChoices();
00258 for(retValue=1;retValue-1<(T)choices.size();++retValue)
00259 if(value == choices[retValue-1])
00260 return retValue;
00261
00262 __SS__ << "\tInvalid value for column data type: " << columnsInfo_[col].getDataType()
00263 << " in configuration " << tableName_
00264 << " at column=" << columnsInfo_[col].getName()
00265 << " for getValue with type '" << ots_demangle(typeid(retValue).name())
00266 << ".'"
00267 << "Attempting to get index of '" << value
00268 << " in fixed choice array, but was not found in array. "
00269 << "Here are the valid choices:\n";
00270 ss << "\t" << ViewColumnInfo::DATATYPE_STRING_DEFAULT << "\n";
00271 for(const auto &choice:choices)
00272 ss << "\t" << choice << "\n";
00273 __MOUT__ << "\n" << ss.str();
00274 throw std::runtime_error(ss.str());
00275 }
00276 }
00277 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_STRING &&
00278 typeid(bool) == typeid(retValue))
00279 {
00280 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_ON_OFF)
00281 retValue = (value == ViewColumnInfo::TYPE_VALUE_ON) ? true:false;
00282 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_TRUE_FALSE)
00283 retValue = (value == ViewColumnInfo::TYPE_VALUE_TRUE) ? true:false;
00284 else if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_YES_NO)
00285 retValue = (value == ViewColumnInfo::TYPE_VALUE_YES) ? true:false;
00286 }
00287 else
00288 {
00289 if(columnsInfo_[col].getType() == ViewColumnInfo::TYPE_FIXED_CHOICE_DATA)
00290 __MOUT_WARN__ << "For column type " << ViewColumnInfo::TYPE_FIXED_CHOICE_DATA
00291 << " the only valid numeric types are 'int' and 'unsigned int.'";
00292
00293 __SS__ << "\tUnrecognized column data type: " << columnsInfo_[col].getDataType()
00294 << " and column type: " << columnsInfo_[col].getType()
00295 << ", in configuration " << tableName_
00296 << " at column=" << columnsInfo_[col].getName()
00297 << " for getValue with type '" << ots_demangle(typeid(retValue).name())
00298 << "'" << std::endl;
00299 throw std::runtime_error(ss.str());
00300 }
00301
00302 return retValue;
00303 }
00304
00305
00306 std::string validateValueForColumn(const std::string& value, unsigned int col, bool convertEnvironmentVariables=true) const;
00307
00308 std::string getValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00309 std::string getEscapedValueAsString(unsigned int row, unsigned int col, bool convertEnvironmentVariables=true) const;
00310 bool isURIEncodedCommentTheSame(const std::string &comment) const;
00311
00312 const DataView& getDataView (void) const;
00313 const std::vector<ViewColumnInfo>& getColumnsInfo (void) const;
00314 std::vector<ViewColumnInfo>* getColumnsInfoP(void);
00315 const ViewColumnInfo& getColumnInfo (unsigned int column) const;
00316
00317
00318
00319 void setUniqueStorageIdentifier (const std::string &storageUID);
00320 void setTableName (const std::string &name );
00321 void setComment (const std::string &comment );
00322 void setURIEncodedComment (const std::string &uriComment );
00323 void setAuthor (const std::string &author );
00324 void setCreationTime (time_t t );
00325 void setLastAccessTime (time_t t = time(0) );
00326 void setLooseColumnMatching (bool setValue );
00327
00328
00329 template<class T>
00330 void setVersion (const T &version)
00331 {
00332 version_ = ConfigurationVersion(version);
00333 }
00334
00335
00336
00337
00338 template<class T>
00339 void setValue(const T &value, unsigned int row, unsigned int col)
00340 {
00341 if(!(col < columnsInfo_.size() && row < getNumberOfRows()))
00342 {
00343 __SS__ << "Invalid row (" << row << ") col (" << col << ") requested!" << std::endl;
00344 throw std::runtime_error(ss.str());
00345 }
00346
00347 if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_NUMBER)
00348 {
00349 std::stringstream ss;
00350 ss << value;
00351 theDataView_[row][col] = ss.str();
00352 }
00353 else if(columnsInfo_[col].getDataType() == ViewColumnInfo::DATATYPE_TIME &&
00354 typeid(time_t) == typeid(value))
00355 {
00356
00357 std::stringstream ss;
00358 ss << value;
00359 theDataView_[row][col] = ss.str();
00360 }
00361 else
00362 {
00363 __SS__ << "\tUnrecognized view data type: " << columnsInfo_[col].getDataType()
00364 << " in configuration " << tableName_
00365 << " at column=" << columnsInfo_[col].getName()
00366 << " for setValue with type '" << ots_demangle(typeid(value).name())
00367 << "'" << std::endl;
00368 throw std::runtime_error(ss.str());
00369 }
00370 }
00371 void setValue (const std::string &value, unsigned int row, unsigned int col);
00372 void setValue (const char *value, unsigned int row, unsigned int col);
00373
00374
00375 void setValueAsString (const std::string &value, unsigned int row, unsigned int col);
00376
00377
00378 void resizeDataView (unsigned int nRows, unsigned int nCols);
00379 int addRow (const std::string &author = "");
00380 void deleteRow (int r);
00381
00382
00383
00384
00385 iterator begin (void) {return theDataView_.begin();}
00386 iterator end (void) {return theDataView_.end();}
00387 const_iterator begin (void) const {return theDataView_.begin();}
00388 const_iterator end (void) const {return theDataView_.end();}
00389 void reset (void);
00390 void print (std::ostream &out = std::cout) const;
00391 void printJSON (std::ostream &out = std::cout) const;
00392 int fillFromJSON (const std::string &json);
00393 int fillFromCSV (const std::string &data, const int &dataOffset = 0, const std::string &author = "") throw(std::runtime_error);
00394 bool setURIEncodedValue (const std::string &value, const unsigned int &row, const unsigned int &col, const std::string &author = "");
00395
00396 static std::string decodeURIComponent (const std::string& data);
00397
00398 private:
00399 const unsigned int getOrInitColUID (void);
00400
00401 ConfigurationView& operator= (const ConfigurationView src);
00402
00403
00404 std::string convertEnvVariables (const std::string& data) const;
00405 bool isNumber (const std::string& s) const;
00406
00407 std::string uniqueStorageIdentifier_;
00408 std::string tableName_ ;
00409 ConfigurationVersion version_ ;
00410 std::string comment_ ;
00411 std::string author_ ;
00412 time_t creationTime_ ;
00413 time_t lastAccessTime_ ;
00414 unsigned int colUID_ ;
00415 std::map<std::string, unsigned int> colLinkGroupIDs_;
00416
00417 bool fillWithLooseColumnMatching_;
00418 unsigned int sourceColumnMismatchCount_, sourceColumnMissingCount_;
00419 std::set<std::string> sourceColumnNames_;
00420
00421 std::vector<ViewColumnInfo> columnsInfo_ ;
00422 DataView theDataView_ ;
00423 };
00424 }
00425
00426
00427
00428 #endif