#ifndef __JDB_JDBREADER__ #define __JDB_JDBREADER__ #include #include #include "dbclient/KM3NeTDBClient.h" #include "JLang/JNullStream.hh" #include "JLang/JEquationParameters.hh" #include "JLang/JRedirectString.hh" #include "JLang/JSingleton.hh" #include "JLang/JLangToolkit.hh" #include "JROOT/JRootClass.hh" #include "JROOT/JRootDictionary.hh" #include "JROOT/JRootStreamer.hh" #include "JDB/JDBDictionary.hh" /** * \author mdejong */ namespace JDATABASE {} namespace JPP { using namespace JDATABASE; } namespace JDATABASE { using JLANG::JSingleton; using KM3NeT::DB::ResultSet; using KM3NeT::DB::Selector; using JROOT::JRootReader; /** * Special characters. */ static const std::string SPECIAL_CHARACTERS = "!@#$%^&*()-+=[]{};:'\"\\|,.<>/?"; /** * Read object with ROOT dictionary from selector. * * \param selection selection * \param object object * \return true if read; else false */ template inline bool operator>>(const std::vector& selection, T& object) { using namespace std; using namespace JPP; JRootReader reader(null, JEquationParameters(), JDBDictionary::getInstance()); JRootReadableClass cls(object); for (vector::const_iterator i = selection.begin(); i != selection.end(); ++i) { string parameter = to_upper(i->Name); for (string::const_iterator i = SPECIAL_CHARACTERS.begin(); i != SPECIAL_CHARACTERS.end(); ++i) { for (string::size_type pos; (pos = parameter.find(*i)) != string::npos; ) { parameter.erase(pos); } } JRootReadableClass abc = cls.find(parameter.c_str()); if (abc.is_valid()) { JRedirectString redirect(reader, i->Value); reader.getObject(abc); } } return true; } /** * Auxiliary class to read object with ROOT dictionary from database. * * The names of the table columns are one-to-one mapped to the names of the data members * of the corresponding data structure using the corresponding ROOT dictionary.\n * For this, all special characters (JDATABASE::SPECIAL_CHARACTERS) are removed from the column names.\n * The static method JDBReader::set can be used to a priori assign default values * to those data members that are defined by the selector used in the query.\n * Note that the list of column names associated to the template parameter is considered to be permanent.\n * If not, the static method JDBReader::reset should be called before the next read operation. */ template struct JDBReader : public JRootReader, public JSingleton< JDBReader > { /** * Default constructor. */ JDBReader() : JRootReader(JLANG::null, JLANG::JEquationParameters(), JDBDictionary::getInstance()) {} /** * Reset internal lookup table and default value. */ static void reset() { JDBReader::getInstance().columns.clear(); JDBReader::getInstance().value = T(); } /** * Set default value corresponding to given selection. * * \param selection selection */ static void set(const std::vector& selection) { selection >> JDBReader::getInstance().value; } /** * Read object with ROOT dictionary from result set. * * \param rs result set * \return object */ const T& operator()(ResultSet& rs) { using namespace std; using namespace JPP; object = value; if (columns.empty()) { JRootReadableClass cls(object); for (size_t i = 0; i != rs.FieldCount(); ++i) { string parameter = rs.FieldName(i); for (string::const_iterator i = SPECIAL_CHARACTERS.begin(); i != SPECIAL_CHARACTERS.end(); ++i) { for (string::size_type pos; (pos = parameter.find(*i)) != string::npos; ) { parameter.erase(pos); } } columns.push_back(cls.find(parameter.c_str())); } } for (unsigned int i = 0; i != rs.FieldCount(); ++i) { if (columns[i].is_valid()) { JRedirectString redirect(*this, rs.GetString(i)); this->getObject(columns[i]); } } return object; } private: T object; //!< internal value T value; //!< default value std::vector columns; //!< field count -> data member }; /** * Read object with ROOT dictionary from result set. * * \param rs result set * \param object object * \return true if read; else false */ template inline bool operator>>(ResultSet& rs, T& object) { JDBReader& reader = JDBReader::getInstance(); if (rs.Next()) { object = reader(rs); return true; } return false; } /** * Read multiple objects with ROOT dictionary from result set. * * \param rs result set * \param buffer container of objects with ROOT dictionary * \return true if read; else false */ template inline bool operator>>(ResultSet& rs, std::vector& buffer) { for (JElement_t object; rs >> object; ) { buffer.push_back(object); } return true; } } #endif