RDKit
Open-source cheminformatics and machine learning.
Query.h
Go to the documentation of this file.
1 //
2 // Copyright (c) 2003-2006 Greg Landrum and Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10 #include <RDGeneral/export.h>
11 #ifndef __RD_QUERY_H__
12 #define __RD_QUERY_H__
13 
14 #ifdef _MSC_VER
15 #pragma warning(disable : 4800) // warning: converting things to bool
16 #endif
17 
18 #include <vector>
19 #include <string>
20 #include <boost/smart_ptr.hpp>
21 #include <RDGeneral/Invariant.h>
22 
23 namespace Queries {
24 
25 //! class to allow integer values to pick templates
26 template <int v>
27 class Int2Type {
28  enum { value = v };
29 };
30 
31 //! Base class for all queries
32 /*!
33  Query objects have one or two functions associated with them:
34  - <tt>bool matchFunc(MatchFuncArgType other)</tt> returns true or false
35  to indicate whether this query matches \c other.
36  This is mandatory.
37 
38  - <tt>MatchFuncArgType dataFunc(DataFuncArgType other)</tt> converts
39  the argument \c other from \c DataFuncArgType to \c MatchFuncArgType.
40  This is optional if \c DataFuncArgType is the same as (or implicitly
41  convertible to) \c MatchFuncArgType.
42 
43 */
44 template <class MatchFuncArgType, class DataFuncArgType = MatchFuncArgType,
45  bool needsConversion = false>
46 class Query {
47  public:
48  typedef boost::shared_ptr<
50  typedef std::vector<CHILD_TYPE> CHILD_VECT;
51  typedef typename CHILD_VECT::iterator CHILD_VECT_I;
52  typedef typename CHILD_VECT::const_iterator CHILD_VECT_CI;
53 
55  : d_description(""),
56  df_negate(false),
57  d_matchFunc(NULL),
58  d_dataFunc(NULL){};
59  virtual ~Query() { this->d_children.clear(); };
60 
61  //! sets whether or not we are negated
62  void setNegation(bool what) { this->df_negate = what; };
63  //! returns whether or not we are negated
64  bool getNegation() const { return this->df_negate; };
65 
66  //! sets our text description
67  void setDescription(const std::string &descr) {
68  this->d_description = descr;
69  };
70  //! \overload
71  void setDescription(const char *descr) {
72  this->d_description = std::string(descr);
73  };
74  //! returns our text description
75  const std::string &getDescription() const { return this->d_description; };
76  //! returns a fuller text description
77  virtual std::string getFullDescription() const {
78  if (!getNegation())
79  return getDescription();
80  else
81  return "not " + getDescription();
82  }
83 
84  //! sets our match function
85  void setMatchFunc(bool (*what)(MatchFuncArgType)) {
86  this->d_matchFunc = what;
87  };
88  //! returns our match function:
89  bool (*getMatchFunc() const)(MatchFuncArgType) { return this->d_matchFunc; };
90  //! sets our data function
91  void setDataFunc(MatchFuncArgType (*what)(DataFuncArgType)) {
92  this->d_dataFunc = what;
93  };
94  //! returns our data function:
95  MatchFuncArgType (*getDataFunc() const)(DataFuncArgType) {
96  return this->d_dataFunc;
97  };
98 
99  //! adds a child to our list of children
100  void addChild(CHILD_TYPE child) { this->d_children.push_back(child); };
101  //! returns an iterator for the beginning of our child vector
102  CHILD_VECT_CI beginChildren() const { return this->d_children.begin(); }
103  //! returns an iterator for the end of our child vector
104  CHILD_VECT_CI endChildren() const { return this->d_children.end(); }
105 
106  //! returns whether or not we match the argument
107  virtual bool Match(const DataFuncArgType arg) const {
108  MatchFuncArgType mfArg = TypeConvert(arg, Int2Type<needsConversion>());
109  bool tRes;
110  if (this->d_matchFunc)
111  tRes = this->d_matchFunc(mfArg);
112  else
113  tRes = static_cast<bool>(mfArg);
114 
115  if (this->getNegation())
116  return !tRes;
117  else
118  return tRes;
119  };
120 
121  //! returns a copy of this Query
122  /*!
123  <b>Notes:</b>
124  - the caller is responsible for <tt>delete</tt>ing the result
125  */
127  const {
130  typename Query<MatchFuncArgType, DataFuncArgType,
131  needsConversion>::CHILD_VECT_CI iter;
132  for (iter = this->beginChildren(); iter != this->endChildren(); ++iter) {
133  res->addChild(CHILD_TYPE(iter->get()->copy()));
134  }
135  res->df_negate = this->df_negate;
136  res->d_matchFunc = this->d_matchFunc;
137  res->d_dataFunc = this->d_dataFunc;
138  res->d_description = this->d_description;
139  return res;
140  };
141 
142  protected:
143  std::string d_description;
144  CHILD_VECT d_children;
145  bool df_negate;
146  bool (*d_matchFunc)(MatchFuncArgType);
147 
148  // MSVC complains at compile time when TypeConvert(MatchFuncArgType what, Int2Type<false>)
149  // attempts to pass what (which is of type MatchFuncArgType) as parameter of d_dataFunc()
150  // (which should be of type DataFuncArgType). The union is but a trick to avoid
151  // silly casts and keep MSVC happy when building DLLs
152  union {
153  MatchFuncArgType (*d_dataFunc)(DataFuncArgType);
154  MatchFuncArgType (*d_dataFuncSameType)(MatchFuncArgType);
155  };
156  //! \brief calls our \c dataFunc (if it's set) on \c what and returns
157  //! the result, otherwise returns \c what
158  MatchFuncArgType TypeConvert(MatchFuncArgType what,
159  Int2Type<false> /*d*/) const {
160  MatchFuncArgType mfArg;
161  if (this->d_dataFuncSameType != NULL && std::is_same<MatchFuncArgType, DataFuncArgType>::value) {
162  mfArg = this->d_dataFuncSameType(what);
163  } else {
164  mfArg = what;
165  }
166  return mfArg;
167  }
168  //! calls our \c dataFunc (which must be set) on \c what and returns the
169  //result
170  MatchFuncArgType TypeConvert(DataFuncArgType what,
171  Int2Type<true> /*d*/) const {
172  PRECONDITION(this->d_dataFunc, "no data function");
173  MatchFuncArgType mfArg;
174  mfArg = this->d_dataFunc(what);
175  return mfArg;
176  }
177 };
178 
179 //----------------------------
180 //
181 // Used within query functions to compare values
182 //
183 //----------------------------
184 template <class T1, class T2>
185 int queryCmp(const T1 v1, const T2 v2, const T1 tol) {
186  T1 diff = v1 - v2;
187  if (diff <= tol) {
188  if (diff >= -tol) {
189  return 0;
190  } else {
191  return -1;
192  }
193  } else {
194  return 1;
195  }
196 };
197 }
198 #endif
virtual std::string getFullDescription() const
returns a fuller text description
Definition: Query.h:77
int queryCmp(const T1 v1, const T2 v2, const T1 tol)
Definition: Query.h:185
virtual bool Match(const DataFuncArgType arg) const
returns whether or not we match the argument
Definition: Query.h:107
void setNegation(bool what)
sets whether or not we are negated
Definition: Query.h:62
MatchFuncArgType TypeConvert(DataFuncArgType what, Int2Type< true >) const
calls our dataFunc (which must be set) on what and returns the
Definition: Query.h:170
boost::shared_ptr< Query< MatchFuncArgType, DataFuncArgType, needsConversion > > CHILD_TYPE
Definition: Query.h:49
bool getNegation() const
returns whether or not we are negated
Definition: Query.h:64
CHILD_VECT::iterator CHILD_VECT_I
Definition: Query.h:51
MatchFuncArgType(*)(DataFuncArgType) getDataFunc() const
returns our data function:
Definition: Query.h:95
CHILD_VECT_CI endChildren() const
returns an iterator for the end of our child vector
Definition: Query.h:104
void setMatchFunc(bool(*what)(MatchFuncArgType))
sets our match function
Definition: Query.h:85
bool(* d_matchFunc)(MatchFuncArgType)
Definition: Query.h:146
std::vector< CHILD_TYPE > CHILD_VECT
Definition: Query.h:50
class to allow integer values to pick templates
Definition: Query.h:27
CHILD_VECT d_children
Definition: Query.h:144
void setDescription(const char *descr)
Definition: Query.h:71
void addChild(CHILD_TYPE child)
adds a child to our list of children
Definition: Query.h:100
MatchFuncArgType(* d_dataFunc)(DataFuncArgType)
Definition: Query.h:153
bool df_negate
Definition: Query.h:145
virtual ~Query()
Definition: Query.h:59
bool(*)(MatchFuncArgType) getMatchFunc() const
returns our match function:
Definition: Query.h:89
void setDataFunc(MatchFuncArgType(*what)(DataFuncArgType))
sets our data function
Definition: Query.h:91
CHILD_VECT_CI beginChildren() const
returns an iterator for the beginning of our child vector
Definition: Query.h:102
CHILD_VECT::const_iterator CHILD_VECT_CI
Definition: Query.h:52
#define PRECONDITION(expr, mess)
Definition: Invariant.h:108
std::string d_description
Definition: Query.h:140
const std::string & getDescription() const
returns our text description
Definition: Query.h:75
MatchFuncArgType TypeConvert(MatchFuncArgType what, Int2Type< false >) const
calls our dataFunc (if it&#39;s set) on what and returns the result, otherwise returns what ...
Definition: Query.h:158
Base class for all queries.
Definition: Query.h:46
void setDescription(const std::string &descr)
sets our text description
Definition: Query.h:67
virtual Query< MatchFuncArgType, DataFuncArgType, needsConversion > * copy() const
returns a copy of this Query
Definition: Query.h:126