Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:31:06

0001 #ifndef CondTools_L1Trigger_RecordHelper_h
0002 #define CondTools_L1Trigger_RecordHelper_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     L1Trigger
0006 // Class  :     RecordHelper
0007 //
0008 /**\class RecordHelper RecordHerlper.h CondTools/L1Trigger/interface/RecordHelper.h
0009 
0010  Description: A microframework to deal with the need to fill rather boring getter/setter classes
0011               from Coral classes.
0012 
0013 
0014 */
0015 
0016 #include <boost/type_traits.hpp>
0017 
0018 #include "RelationalAccess/ICursor.h"
0019 #include "CoralBase/AttributeList.h"
0020 #include "CoralBase/AttributeSpecification.h"
0021 #include "CoralBase/Attribute.h"
0022 
0023 /** A C++ version of C's strupper */
0024 std::string upcaseString(std::string aString);
0025 
0026 /** A base class for all field handlers that create TOutput C++ objects. */
0027 template <class TOutput>
0028 class FieldHandlerBase {
0029 public:
0030   typedef coral::AttributeList AttributeList;
0031   /** Construct a new field handler with the C++ field name as its argument */
0032   FieldHandlerBase(const std::string& name) : name_(name) {}
0033 
0034   /** Return the name of the field handled by this object. */
0035   const std::string& getName() { return name_; }
0036 
0037   /** Return the name of the associated database field. For the GMT database,
0038    *  this simply corresponds to the uppercased field name. */
0039   virtual const std::string getColumnName() { return upcaseString(name_); }
0040 
0041   /** The actual extraction function. src contains a CORAL attribute list representing a 
0042    *  query result row, dest is the output object to be filled. */
0043   virtual void extractValue(const AttributeList& src, TOutput& dest) = 0;
0044 
0045   /** Virtual destructor for children. */
0046   virtual ~FieldHandlerBase() {}
0047 
0048 private:
0049   /* The (case sensitive!) name of the field. */
0050   std::string name_;
0051 };
0052 
0053 /** A template field handler that simply 
0054  *    - casts the data field to TCField
0055  *    - converts that value to TCField
0056  *    - passes it to a setter method of a TOutput object
0057  */
0058 template <class TOutput, class TCField, class TDBField>
0059 class FieldHandler : public FieldHandlerBase<TOutput> {
0060 public:
0061   typedef coral::AttributeList AttributeList;
0062   typedef void (TOutput::*TSetMethod)(const TCField);
0063 
0064   FieldHandler(const std::string& fieldName, TSetMethod setter)
0065       : FieldHandlerBase<TOutput>(fieldName), setter_(setter) {}
0066 
0067   /** Actual data extraction. */
0068   void extractValue(const AttributeList& src, TOutput& dest) override {
0069 #ifdef RECORDHELPER_DEBUG
0070     std::cout << "Parsing field " << this->getName() << " with type " << typeid(TCField).name();
0071 #endif
0072     typedef typename boost::remove_cv<typename boost::remove_reference<TDBField>::type>::type TDBFieldT;
0073     const TDBFieldT& value = src[this->getColumnName()].template data<TDBFieldT>();
0074     ((dest).*setter_)(TCField(value));
0075 
0076 #ifdef RECORDHELPER_DEBUG
0077     std::cout << "=" << TCField(value) << std::endl;
0078 #endif
0079   }
0080 
0081 protected:
0082   /** Points to the setter method used to stuff the field's value into the
0083      destination object. */
0084   TSetMethod setter_;
0085 };
0086 
0087 /** A special handler for bool fields in the GT/GMT DBs. These can't be imported
0088  *  in the generic way because bool values are returned as char '0' for false and 
0089  * '1' for true from the database. Basically, all values that are != FalseCharacter
0090  *  are treated as true (in adherence to the venerable C tradition).
0091  */
0092 template <class TOutput, char FalseCharacter>
0093 class ASCIIBoolFieldHandler : public FieldHandler<TOutput, bool, char> {
0094 public:
0095   typedef coral::AttributeList AttributeList;
0096   ASCIIBoolFieldHandler(const std::string& fieldName, typename FieldHandler<TOutput, bool, char>::TSetMethod setter)
0097       : FieldHandler<TOutput, bool, char>(fieldName, setter) {}
0098 
0099   /** Extract value as char, then see compare it to '0' to get its truth value. */
0100   void extractValue(const AttributeList& src, TOutput& dest) override {
0101     char value = src[this->getColumnName()].template data<char>();
0102 #ifdef RECORDHELPER_DEBUG
0103     std::cout << " .. and " << this->getColumnName() << " is (in integers) " << (int)value << std::endl;
0104 #endif
0105     ((dest).*(this->setter_))(value != FalseCharacter);
0106   }
0107 };
0108 
0109 /** Tag class: Allow overriding of field type -> field handler type mapping
0110                according to the group that a type is added to. This means that
0111            we can override the standard type mappings for some functions. */
0112 
0113 /** The standard group: All types for which no explicit group is defined end up 
0114     here. */
0115 class TStandardGroup;
0116 
0117 /** Generic mapping - all types get TStandardGroup. */
0118 template <typename TOutput>
0119 struct Group {
0120   typedef TStandardGroup Type;
0121 };
0122 
0123 /** A macro that assigns a record type to a group. */
0124 #define RH_ASSIGN_GROUP(TOutput, TGroup) \
0125   template <>                            \
0126   struct Group<TOutput> {                \
0127     typedef TGroup Type;                 \
0128   };
0129 
0130 /** What is all this group stuff good for? It provides a layer of indirection
0131     between output types and field handlers that is not specific to each type,
0132     so that it's possible to handle a bunch of types with a uniform database column ->
0133     field structure mapping with just one group def + 1 RH_ASSIGN_GROUP per type.
0134 */
0135 
0136 /* Generically: We don't mess with types and expect the field types to
0137    exactly match the database types (sadly, CORAL is rather anal about
0138    such things). */
0139 template <typename TOutput, typename TGroup, typename TCType>
0140 struct GroupFieldHandler {
0141   typedef FieldHandler<TOutput, TCType, TCType> Type;
0142 };
0143 
0144 template <class TOutput>
0145 class RecordHelper {
0146 public:
0147   typedef coral::AttributeList AttributeList;
0148   /** A list of field handlers that determine how to handle a record. */
0149   typedef std::vector<FieldHandlerBase<TOutput>*> FieldVector;
0150 
0151   template <typename TField>
0152   void addField(const std::string& fieldName, void (TOutput::*setter)(const TField)) {
0153 #ifdef RECORDHELPER_DEBUG
0154     std::cout << "Adding field " << fieldName << ", type = " << typeid(TField).name() << std::endl;
0155 #endif
0156     this->fields_.push_back(
0157         new typename GroupFieldHandler<TOutput, typename Group<TOutput>::Type, TField>::Type(fieldName, setter));
0158   }
0159 
0160   /** Iterates over all known fields and extracts the fields of the record
0161       in source to the object in dest. */
0162   virtual void extractRecord(const AttributeList& source, TOutput& dest) {
0163     for (typename FieldVector::const_iterator it = fields_.begin(); it != fields_.end(); ++it) {
0164       (*it)->extractValue(source, dest);
0165     }
0166   }
0167 
0168   /** Returns a list of database column names for the added fields. */
0169   virtual std::vector<std::string> getColumnList() {
0170     std::vector<std::string> colList;
0171     for (typename FieldVector::const_iterator it = fields_.begin(); it != fields_.end(); ++it) {
0172       colList.push_back((*it)->getColumnName());
0173     }
0174 
0175     return colList;
0176   }
0177 
0178   /** Destructor: Wipe out all the field handlers. */
0179   virtual ~RecordHelper() {
0180     for (typename FieldVector::iterator it = fields_.begin(); it < fields_.end(); ++it) {
0181       delete *it;
0182     }
0183   }
0184 
0185 protected:
0186   /** List of known fields. TODO: Make private, add base type addField. */
0187   FieldVector fields_;
0188 };
0189 
0190 /** A helper macro to reduce the amount of typing, since
0191    the field name completely determines the setter. */
0192 #define ADD_FIELD(HELPER, OUTPUT_NAME, FIELD_NAME) HELPER.addField(#FIELD_NAME, &OUTPUT_NAME::set##FIELD_NAME);
0193 
0194 #endif