Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:17

0001 #ifndef CondTools_RunInfo_OMSAccess_h
0002 #define CondTools_RunInfo_OMSAccess_h
0003 
0004 #include <string>
0005 #include <stdexcept>
0006 #include <boost/property_tree/ptree.hpp>
0007 #include <boost/property_tree/json_parser.hpp>
0008 #include <boost/date_time/posix_time/posix_time.hpp>
0009 #include <memory>
0010 
0011 namespace cond {
0012 
0013   // implementation details for data extraction from json/ data conversion to build query urls
0014   namespace impl {
0015 
0016     static constexpr const char* const OMS_TIME_FMT = "%Y-%m-%dT%H:%M:%SZ";
0017 
0018     template <typename T, T fun(const std::string&)>
0019     inline T from_string_impl(const std::string& attributeValue, T zero) {
0020       T ret = zero;
0021       if (not attributeValue.empty() && attributeValue != "null") {
0022         ret = fun(attributeValue);
0023       }
0024       return ret;
0025     }
0026 
0027     template <typename T>
0028     inline T from_string(const std::string& attributeValue) {
0029       throw std::invalid_argument("");
0030     }
0031 
0032     template <>
0033     inline std::string from_string(const std::string& attributeValue) {
0034       return std::string(attributeValue);
0035     }
0036 
0037     inline float s_to_f(const std::string& val) { return std::stof(val); }
0038     template <>
0039     inline float from_string(const std::string& attributeValue) {
0040       return from_string_impl<float, &s_to_f>(attributeValue, 0.);
0041     }
0042 
0043     inline int s_to_i(const std::string& val) { return std::stoi(val); }
0044     template <>
0045     inline int from_string(const std::string& attributeValue) {
0046       return from_string_impl<int, &s_to_i>(attributeValue, 0);
0047     }
0048 
0049     inline unsigned long s_to_ul(const std::string& val) { return std::stoul(val); }
0050     template <>
0051     inline unsigned short from_string(const std::string& attributeValue) {
0052       unsigned long int_val = from_string_impl<unsigned long, &s_to_ul>(attributeValue, 0);
0053       return (unsigned short)int_val;
0054     }
0055     inline unsigned long long s_to_ull(const std::string& val) { return std::stoull(val); }
0056     template <>
0057     inline unsigned long long from_string(const std::string& attributeValue) {
0058       unsigned long long int_val = from_string_impl<unsigned long long, &s_to_ull>(attributeValue, 0);
0059       return int_val;
0060     }
0061 
0062     inline boost::posix_time::ptime s_to_time(const std::string& val) {
0063       boost::posix_time::time_input_facet* facet = new boost::posix_time::time_input_facet(OMS_TIME_FMT);
0064       std::stringstream ss;
0065       ss.imbue(std::locale(std::locale(), facet));
0066       ss << val;
0067       boost::posix_time::ptime time;
0068       ss >> time;
0069       return time;
0070     }
0071     template <>
0072     inline boost::posix_time::ptime from_string(const std::string& attributeValue) {
0073       return from_string_impl<boost::posix_time::ptime, &s_to_time>(attributeValue, boost::posix_time::ptime());
0074     }
0075 
0076     template <typename V>
0077     inline std::string to_string(const V& value) {
0078       return std::to_string(value);
0079     }
0080     template <typename V>
0081     inline std::string to_string(const V* value) {
0082       return std::to_string(*value);
0083     }
0084     template <>
0085     inline std::string to_string(const std::string& value) {
0086       return std::string(value);
0087     }
0088     template <>
0089     inline std::string to_string(const char* value) {
0090       return std::string(value);
0091     }
0092     template <>
0093     inline std::string to_string(const boost::posix_time::ptime& value) {
0094       boost::posix_time::time_facet* facet = new boost::posix_time::time_facet();
0095       facet->format(OMS_TIME_FMT);
0096       std::stringstream stream;
0097       stream.imbue(std::locale(std::locale::classic(), facet));
0098       stream << value;
0099       return stream.str();
0100     }
0101 
0102   }  // namespace impl
0103 
0104   // reference of a result set row. it does not own/hold data.
0105   class OMSServiceResultRef {
0106   public:
0107     OMSServiceResultRef() = delete;
0108     OMSServiceResultRef(const boost::property_tree::ptree* row);
0109 
0110     // return true if no attribute is available
0111     bool empty();
0112     // typed getter for single param
0113     template <typename T>
0114     inline T get(const std::string& attributeName) {
0115       return impl::from_string<T>(getAttribute(attributeName));
0116     }
0117     // getter for arrays
0118     template <typename primitive>
0119     std::vector<primitive> getArray(const std::string& attributeName) {
0120       std::vector<primitive> ret;
0121       for (auto& item : m_row->get_child(attributeName)) {
0122         ret.push_back(item.second.get_value<primitive>());
0123       }
0124       return ret;
0125     }
0126 
0127   private:
0128     std::string getAttribute(const std::string& attributeName);
0129     const boost::property_tree::ptree* m_row = nullptr;
0130   };
0131 
0132   // iterator object for result
0133   class OMSServiceResultIterator {
0134   public:
0135     OMSServiceResultIterator() = delete;
0136     OMSServiceResultIterator(boost::property_tree::ptree::const_iterator iter);
0137 
0138     OMSServiceResultRef operator*();
0139     OMSServiceResultIterator& operator++();
0140 
0141     bool operator==(const OMSServiceResultIterator& rhs);
0142     bool operator!=(const OMSServiceResultIterator& rhs);
0143 
0144   private:
0145     boost::property_tree::ptree::const_iterator m_iter;
0146   };
0147 
0148   // container wrapping the query result, based on boost property tree
0149   class OMSServiceResult {
0150   public:
0151     OMSServiceResult();
0152     // basic iterators, to enable the C++11 for loop semantics
0153     OMSServiceResultIterator begin() const;
0154     OMSServiceResultIterator end() const;
0155 
0156     OMSServiceResultRef front() const;
0157     OMSServiceResultRef back() const;
0158 
0159     // parse json returned from curl, filling the property tree
0160     size_t parseData(const std::string& data);
0161 
0162     // returns the number of top level elements of the tree ( result set "rows" )
0163     size_t size() const;
0164 
0165     // returns size()==0
0166     bool empty() const;
0167 
0168   private:
0169     boost::property_tree::ptree m_root;
0170     boost::property_tree::ptree* m_data;
0171   };
0172 
0173   // Query object
0174   class OMSServiceQuery {
0175   public:
0176     // comparison operator label, used in query urls
0177     static constexpr const char* const NEQ = "NEQ";
0178     static constexpr const char* const EQ = "EQ";
0179     static constexpr const char* const LT = "LT";
0180     static constexpr const char* const LE = "LE";
0181     static constexpr const char* const GT = "GT";
0182     static constexpr const char* const GE = "GE";
0183     static constexpr const char* const SNULL = "null";
0184 
0185   public:
0186     OMSServiceQuery() = delete;
0187     OMSServiceQuery(const std::string& baseUrl, const std::string& function);
0188 
0189     // functions to restring query output to specific variables
0190     OMSServiceQuery& addOutputVar(const std::string& varName);
0191     OMSServiceQuery& addOutputVars(const std::initializer_list<const char*>& varNames);
0192 
0193     // generic query filter
0194     template <typename T>
0195     inline OMSServiceQuery& filter(const char* cmp, const std::string& varName, const T& value) {
0196       std::stringstream filter;
0197       if (m_filter.empty()) {
0198         filter << "?";
0199         if (!m_limit.empty()) {
0200           m_limit.front() = '&';
0201         }
0202       } else {
0203         filter << m_filter << "&";
0204       }
0205       filter << "filter[" << varName << "][" << cmp << "]=" << impl::to_string(value);
0206       m_filter = filter.str();
0207       return *this;
0208     }
0209     // filters with specific comparison operators
0210     template <typename T>
0211     inline OMSServiceQuery& filterEQ(const std::string& varName, const T& value) {
0212       return filter<T>(EQ, varName, value);
0213     }
0214     template <typename T>
0215     inline OMSServiceQuery& filterNEQ(const std::string& varName, const T& value) {
0216       return filter<T>(NEQ, varName, value);
0217     }
0218     template <typename T>
0219     inline OMSServiceQuery& filterGT(const std::string& varName, const T& value) {
0220       return filter<T>(GT, varName, value);
0221     }
0222     template <typename T>
0223     inline OMSServiceQuery& filterGE(const std::string& varName, const T& value) {
0224       return filter<T>(GE, varName, value);
0225     }
0226     template <typename T>
0227     inline OMSServiceQuery& filterLT(const std::string& varName, const T& value) {
0228       return filter<T>(LT, varName, value);
0229     }
0230     template <typename T>
0231     inline OMSServiceQuery& filterLE(const std::string& varName, const T& value) {
0232       return filter<T>(LE, varName, value);
0233     }
0234     // not null filter
0235     inline OMSServiceQuery& filterNotNull(const std::string& varName) { return filterNEQ(varName, SNULL); }
0236 
0237     // limit for the page size, when unspecified OMS's default limit is 100
0238     OMSServiceQuery& limit(int value);
0239 
0240     // triggers the execution of the query ( calling curl functions )
0241     bool execute();
0242 
0243     // return code from curl
0244     unsigned long status();
0245 
0246     // result from the query. memory allocated for data is owned by the query object itself
0247     OMSServiceResult& result();
0248 
0249     // the url constructed and used for the query
0250     std::string url();
0251 
0252   private:
0253     void addVar(const std::string& varName);
0254 
0255   private:
0256     std::string m_url;
0257     std::string m_filter;
0258     std::string m_limit;
0259     std::string m_varList;
0260     std::unique_ptr<OMSServiceResult> m_result;
0261     unsigned long m_status = 0;
0262   };
0263 
0264   // provides query access to OMS Web services
0265   class OMSService {
0266   public:
0267     OMSService();
0268 
0269     void connect(const std::string& baseUrl);
0270     std::unique_ptr<OMSServiceQuery> query(const std::string& function) const;
0271 
0272   private:
0273     std::string m_baseUrl;
0274   };
0275 }  // namespace cond
0276 
0277 #endif