#ifndef __JDB_JSELECTOR__ #define __JDB_JSELECTOR__ #include #include #include #include #include "JLang/JException.hh" #include "JLang/JLangToolkit.hh" #include "JMath/JMath.hh" #include "dbclient/KM3NeTDBClient.h" /** * \author mdejong */ namespace JDATABASE {}; namespace JPP { using namespace JDATABASE; } namespace JDATABASE { using JMATH::JMath; using JLANG::JIndexOutOfRange; using KM3NeT::DB::Selector; /** * Available operands. */ static const Selector::RelOp* const OPERAND[] = { &Selector::RelOp::Equal, &Selector::RelOp::Different, &Selector::RelOp::Less, &Selector::RelOp::LessEqual, &Selector::RelOp::Greater, &Selector::RelOp::GreaterEqual }; /** * Number of available operands. */ static const int NUMBER_OF_OPERANDS = sizeof(OPERAND) / sizeof(OPERAND[0]); /** * Get operand. * * \param index index * \return operand */ inline const Selector::RelOp& getOperand(const int index) { if (index >= 0 && index <= NUMBER_OF_OPERANDS) return *OPERAND[index]; else THROW(JIndexOutOfRange, "Invalid index " << index); } /** * Auxiliary class for specifying selection of database data. */ class JSelector : public std::vector, public JMath { public: /** * End-of-line. */ static const char EOL = ';'; /** * Default constructor. */ JSelector() {} /** * Constructor. * * \param key key * \param value value * \param operand operand */ template JSelector(const std::string& key, const T value, const Selector::RelOp& operand = Selector::RelOp::Equal) { add(key, value, operand); } /** * Constructor. * * \param data_member data member * \param value value * \param operand operand */ template JSelector(JType_t JClass_t::*data_member, const JType_t value, const Selector::RelOp& operand = Selector::RelOp::Equal) { add(data_member, value, operand); } /** * Constructor. * * \param data_member data member * \param value value * \param operand operand */ template JSelector(std::string JClass_t::*data_member, const std::string value, const Selector::RelOp& operand = Selector::RelOp::Equal) { add(data_member, value, operand); } /** * Add selection. * * \param selection selection * \return this selection */ JSelector& add(const JSelector& selection) { using namespace std; copy(selection.begin(), selection.end(), back_inserter(*this)); return *this; } /** * Add selection. * * \param key key * \param value value * \param operand operand * \return this selection */ template JSelector& add(const std::string& key, const T value, const Selector::RelOp& operand = Selector::RelOp::Equal) { using namespace std; ostringstream os; os << value; push_back(Selector(key.c_str(), os.str().c_str(), operand)); return *this; } /** * Add selection. * * \param data_member data member * \param value value * \param operand operand * \return this selection */ template inline JSelector& add(JType_t JClass_t::*data_member, const JType_t value, const Selector::RelOp& operand = Selector::RelOp::Equal) { return add(getColumn(data_member), value, operand); } /** * Add selection. * * \param data_member data member * \param value value * \param operand operand * \return this selection */ template inline JSelector& add(std::string JClass_t::*data_member, const std::string& value, const Selector::RelOp& operand = Selector::RelOp::Equal) { return add(getColumn(data_member), value, operand); } /** * Read selector from input stream. * * \param in input stream * \param selector selector * \return input stream */ friend inline std::istream& operator>>(std::istream& in, JSelector& selector) { using namespace std; using namespace JPP; for (string buffer; getline(in, buffer, JSelector::EOL); ) { int operand = -1; for (int i = 0; i != NUMBER_OF_OPERANDS; ++i) { const string::size_type pos = buffer.find(getOperand(i).Render()); if (pos != string::npos && (operand == -1 || getOperand(i).Render().length() > getOperand(operand).Render().length())) { operand = i; } } if (operand != -1) { const string::size_type pos = buffer.find(getOperand(operand).Render()); const string key = JPP::trim(buffer.substr(0, pos)); const string value = JPP::trim(buffer.substr(pos + getOperand(operand).Render().length())); if (key .find_first_of("=!<>") == string::npos && value.find_first_of("=!<>") == string::npos) { selector.push_back(Selector(key.c_str(), value.c_str(), getOperand(operand))); } else { in.setstate(ios::badbit); } } else { in.setstate(ios::badbit); } } return in; } /** * Write selector to output stream. * * \param out output stream * \param selector selector * \return output stream */ friend inline std::ostream& operator<<(std::ostream& out, const JSelector& selector) { for (const_iterator i = selector.begin(); i != selector.end(); ++i) { out << i->Name << i->RelationalOperator.Render() << i->Value << JSelector::EOL << std::endl; } return out; } }; } #endif