Query.h

Go to the documentation of this file.
00001 //
00002 // Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved  @@
00005 //
00006 #ifndef __RD_QUERY_H__
00007 #define __RD_QUERY_H__
00008 
00009 #ifdef _MSC_VER
00010 #pragma warning (disable: 4800) // warning: converting things to bool
00011 #endif
00012 
00013 #include <vector>
00014 #include <string>
00015 #include <boost/smart_ptr.hpp>
00016 #include <RDGeneral/Invariant.h>
00017 
00018 namespace Queries {
00019 
00020   //! class to allow integer values to pick templates
00021   template <int v> 
00022   class Int2Type
00023   {
00024     enum { value = v };
00025   };
00026 
00027   //! Base class for all queries
00028   /*!
00029     Query objects have one or two functions associated with them:
00030       - <tt>bool matchFunc(MatchFuncArgType other)</tt> returns true or false
00031         to indicate whether this query matches \c other.
00032         This is mandatory.
00033 
00034       - <tt>MatchFuncArgType dataFunc(DataFuncArgType other)</tt> converts
00035         the argument \c other from \c DataFuncArgType to \c MatchFuncArgType.
00036         This is optional if \c DataFuncArgType is the same as (or implicitly
00037         convertible to) \c MatchFuncArgType.
00038         
00039   */
00040   template <class MatchFuncArgType, class DataFuncArgType=MatchFuncArgType,
00041     bool needsConversion=false>
00042   class Query {
00043   public:
00044     typedef boost::shared_ptr< Query<MatchFuncArgType, DataFuncArgType, needsConversion> > CHILD_TYPE;
00045     typedef std::vector< CHILD_TYPE > CHILD_VECT;
00046     typedef typename CHILD_VECT::iterator CHILD_VECT_I;
00047     typedef typename CHILD_VECT::const_iterator CHILD_VECT_CI;
00048   
00049     Query() : d_description(""),df_negate(false),d_matchFunc(NULL),d_dataFunc(NULL){};
00050     virtual ~Query() { this->d_children.clear(); };
00051 
00052   
00053     //! sets whether or not we are negated
00054     void setNegation(bool what) { this->df_negate = what; };
00055     //! returns whether or not we are negated
00056     bool getNegation() const { return this->df_negate; };
00057 
00058     //! sets our text description
00059     void setDescription(std::string &descr) { this->d_description = descr; };
00060     //! \overload
00061     void setDescription(const char *descr) { this->d_description = std::string(descr); };
00062     //! returns our text description
00063     std::string getDescription() const { return this->d_description; };
00064 
00065     //! sets our match function
00066     void setMatchFunc(bool (*what)(MatchFuncArgType)) { this->d_matchFunc = what; };
00067     //! returns our match function:
00068     bool (*getMatchFunc() const)(MatchFuncArgType) { return this->d_matchFunc; };
00069     //! sets our data function
00070     void setDataFunc(MatchFuncArgType (*what)(DataFuncArgType)) { this->d_dataFunc = what; };
00071     //! returns our data function:
00072     MatchFuncArgType (*getDataFunc() const)(DataFuncArgType) { return this->d_dataFunc; };
00073 
00074     //! adds a child to our list of children
00075     void addChild(CHILD_TYPE child) { this->d_children.push_back(child); };
00076     //! returns an iterator for the beginning of our child vector
00077     CHILD_VECT_CI beginChildren() const { return this->d_children.begin(); }
00078     //! returns an iterator for the end of our child vector
00079     CHILD_VECT_CI endChildren() const { return this->d_children.end(); }
00080   
00081     //! returns whether or not we match the argument
00082     virtual bool Match(const DataFuncArgType arg) const{
00083       MatchFuncArgType mfArg = TypeConvert(arg,Int2Type<needsConversion>());
00084       bool tRes;
00085       if(this->d_matchFunc) tRes = this->d_matchFunc(mfArg);
00086       else tRes = static_cast<bool>(mfArg);
00087 
00088       if( this->getNegation() ) return !tRes;
00089       else return tRes;
00090     };
00091 
00092     //! returns a copy of this Query
00093     /*!
00094        <b>Notes:</b>
00095          - the caller is responsible for <tt>delete</tt>ing the result
00096      */
00097     virtual Query<MatchFuncArgType,DataFuncArgType,needsConversion> *
00098     copy( ) const {
00099       Query<MatchFuncArgType,DataFuncArgType,needsConversion> *res =
00100         new Query<MatchFuncArgType,DataFuncArgType,needsConversion>();
00101       typename Query<MatchFuncArgType,DataFuncArgType,needsConversion>::CHILD_VECT_CI iter;
00102       for(iter=this->beginChildren();
00103           iter!=this->endChildren();
00104           ++iter){
00105         res->addChild(*iter);
00106       }
00107       res->df_negate = this->df_negate;
00108       res->d_matchFunc = this->d_matchFunc;
00109       res->d_dataFunc = this->d_dataFunc;
00110       res->d_description = this->d_description;
00111       return res;
00112     };
00113 
00114   protected :
00115     std::string d_description;
00116     CHILD_VECT d_children;
00117     bool df_negate;
00118     bool (*d_matchFunc) (MatchFuncArgType);
00119     MatchFuncArgType (*d_dataFunc)(DataFuncArgType);
00120 
00121     //! \brief calls our \c dataFunc (if it's set) on \c what and returns
00122     //! the result, otherwise returns \c what
00123     MatchFuncArgType TypeConvert(MatchFuncArgType what,Int2Type<false> d) const{
00124       MatchFuncArgType mfArg;
00125       if( this->d_dataFunc != NULL ){
00126         mfArg = this->d_dataFunc(what);
00127       } else {
00128         mfArg = what;
00129       }
00130       return mfArg;
00131     }
00132     //! calls our \c dataFunc (which must be set) on \c what and returns the result
00133     MatchFuncArgType TypeConvert(DataFuncArgType what,Int2Type<true> d) const{
00134       PRECONDITION(this->d_dataFunc,"no data function");
00135       MatchFuncArgType mfArg;
00136       mfArg = this->d_dataFunc(what);
00137       return mfArg;
00138     }
00139     
00140 
00141   };
00142 
00143 
00144   //----------------------------
00145   //
00146   // Used within query functions to compare values
00147   //
00148   //----------------------------
00149   template <class T1, class T2>
00150   int queryCmp(const T1 v1, const T2 v2, const T1 tol) {
00151     T1 diff = v1 - v2;
00152     if( diff <= tol ){
00153       if( diff >= -tol ){
00154         return 0;
00155       } else {
00156         return -1;
00157       }
00158     } else {
00159       return 1;
00160     }
00161   };
00162 
00163 
00164 }
00165 #endif

Generated on Tue Oct 7 06:10:11 2008 for RDCode by  doxygen 1.5.5