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