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