1 //  Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc.
2 //  All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 //       notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 //       copyright notice, this list of conditions and the following
12 //       disclaimer in the documentation and/or other materials provided
13 //       with the distribution.
14 //     * Neither the name of Novartis Institutes for BioMedical Research Inc.
15 //       nor the names of its contributors may be used to endorse or promote
16 //       products derived from this software without specific prior written
17 //       permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 //
31 
32 #include <RDGeneral/export.h>
33 #ifndef __RD_FILTER_MATCHER_H__
34 #define __RD_FILTER_MATCHER_H__
35 #include <GraphMol/RDKitBase.h>
36 #include <GraphMol/Substruct/SubstructMatch.h>
37 #include "FilterMatcherBase.h"
38 #include <GraphMol/MolPickler.h>
39 
40 namespace RDKit {
41 
42 namespace {
getArgName(const boost::shared_ptr<FilterMatcherBase> & arg)43 std::string getArgName(const boost::shared_ptr<FilterMatcherBase> &arg) {
44   if (arg.get()) return arg->getName();
45   return "<nullmatcher>";
46 }
47 }  // namespace
48 
49 namespace FilterMatchOps {
50 class RDKIT_FILTERCATALOG_EXPORT And : public FilterMatcherBase {
51   boost::shared_ptr<FilterMatcherBase> arg1;
52   boost::shared_ptr<FilterMatcherBase> arg2;
53 
54  public:
55   // !Default Constructor for serialization
And()56   And() : FilterMatcherBase("And"), arg1(), arg2() {}
57 
58   //! Constructs an Ander
59   //! True if arg1 and arg2 FilterMatchers are true
60 
And(const FilterMatcherBase & arg1,const FilterMatcherBase & arg2)61   And(const FilterMatcherBase &arg1, const FilterMatcherBase &arg2)
62       : FilterMatcherBase("And"), arg1(arg1.copy()), arg2(arg2.copy()) {}
63 
And(const boost::shared_ptr<FilterMatcherBase> & arg1,const boost::shared_ptr<FilterMatcherBase> & arg2)64   And(const boost::shared_ptr<FilterMatcherBase> &arg1,
65       const boost::shared_ptr<FilterMatcherBase> &arg2)
66       : FilterMatcherBase("And"), arg1(arg1), arg2(arg2) {}
67 
And(const And & rhs)68   And(const And &rhs)
69       : FilterMatcherBase(rhs), arg1(rhs.arg1), arg2(rhs.arg2) {}
70 
getName()71   virtual std::string getName() const {
72     return "(" + getArgName(arg1) + " " + FilterMatcherBase::getName() + " " +
73            getArgName(arg2) + ")";
74   }
75 
isValid()76   bool isValid() const {
77     return arg1.get() && arg2.get() && arg1->isValid() && arg2->isValid();
78   }
79 
hasMatch(const ROMol & mol)80   bool hasMatch(const ROMol &mol) const {
81     PRECONDITION(isValid(),
82                  "FilterMatchOps::And is not valid, null arg1 or arg2");
83     return arg1->hasMatch(mol) && arg2->hasMatch(mol);
84   }
85 
getMatches(const ROMol & mol,std::vector<FilterMatch> & matchVect)86   bool getMatches(const ROMol &mol, std::vector<FilterMatch> &matchVect) const {
87     PRECONDITION(isValid(),
88                  "FilterMatchOps::And is not valid, null arg1 or arg2");
89     std::vector<FilterMatch> matches;
90     if (arg1->getMatches(mol, matches) && arg2->getMatches(mol, matches)) {
91       matchVect = matches;
92       return true;
93     }
94     return false;
95   }
96 
copy()97   boost::shared_ptr<FilterMatcherBase> copy() const {
98     return boost::shared_ptr<FilterMatcherBase>(new And(*this));
99   }
100 
101  private:
102 #ifdef RDK_USE_BOOST_SERIALIZATION
103   friend class boost::serialization::access;
104   template <class Archive>
serialize(Archive & ar,const unsigned int version)105   void serialize(Archive &ar, const unsigned int version) {
106     RDUNUSED_PARAM(version);
107     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
108 
109     ar &arg1;
110     ar &arg2;
111   }
112 #endif
113 };
114 
115 class RDKIT_FILTERCATALOG_EXPORT Or : public FilterMatcherBase {
116   boost::shared_ptr<FilterMatcherBase> arg1;
117   boost::shared_ptr<FilterMatcherBase> arg2;
118 
119  public:
120   // !Default Constructor for serialization
Or()121   Or() : FilterMatcherBase("Or"), arg1(), arg2() {}
122 
123   //! Constructs or Ander
124   //! true if arg1 or arg2 are true
Or(const FilterMatcherBase & arg1,const FilterMatcherBase & arg2)125   Or(const FilterMatcherBase &arg1, const FilterMatcherBase &arg2)
126       : FilterMatcherBase("Or"), arg1(arg1.copy()), arg2(arg2.copy()) {}
127 
Or(const boost::shared_ptr<FilterMatcherBase> & arg1,const boost::shared_ptr<FilterMatcherBase> & arg2)128   Or(const boost::shared_ptr<FilterMatcherBase> &arg1,
129      const boost::shared_ptr<FilterMatcherBase> &arg2)
130       : FilterMatcherBase("Or"), arg1(arg1), arg2(arg2) {}
131 
Or(const Or & rhs)132   Or(const Or &rhs) : FilterMatcherBase(rhs), arg1(rhs.arg1), arg2(rhs.arg2) {}
133 
getName()134   virtual std::string getName() const {
135     return "(" + getArgName(arg1) + " " + FilterMatcherBase::getName() + " " +
136            getArgName(arg2) + ")";
137   }
138 
isValid()139   bool isValid() const {
140     return arg1.get() && arg2.get() && arg1->isValid() && arg2->isValid();
141   }
142 
hasMatch(const ROMol & mol)143   bool hasMatch(const ROMol &mol) const {
144     PRECONDITION(isValid(), "Or is not valid, null arg1 or arg2");
145     return arg1->hasMatch(mol) || arg2->hasMatch(mol);
146   }
147 
getMatches(const ROMol & mol,std::vector<FilterMatch> & matchVect)148   bool getMatches(const ROMol &mol, std::vector<FilterMatch> &matchVect) const {
149     PRECONDITION(isValid(),
150                  "FilterMatchOps::Or is not valid, null arg1 or arg2");
151     // we want both matches to run in order to accumulate all matches
152     //  into matchVect, otherwise the or can be arbitrary...
153     bool res1 = arg1->getMatches(mol, matchVect);
154     bool res2 = arg2->getMatches(mol, matchVect);
155     return res1 || res2;
156   }
157 
copy()158   boost::shared_ptr<FilterMatcherBase> copy() const {
159     return boost::shared_ptr<FilterMatcherBase>(new Or(*this));
160   }
161 
162 #ifdef RDK_USE_BOOST_SERIALIZATION
163   friend class boost::serialization::access;
164   template <class Archive>
serialize(Archive & ar,const unsigned int version)165   void serialize(Archive &ar, const unsigned int version) {
166     RDUNUSED_PARAM(version);
167     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
168     ar &arg1;
169     ar &arg2;
170   }
171 #endif
172 };
173 
174 class RDKIT_FILTERCATALOG_EXPORT Not : public FilterMatcherBase {
175   boost::shared_ptr<FilterMatcherBase> arg1;
176 
177  public:
178   // !Default Constructor for serialization
Not()179   Not() : FilterMatcherBase("Not"), arg1() {}
180 
181   //! Constructs a Noter
182   //! true if arg1 is false (note, never returns matches
183   //  from getMatches since a false internal match matches
184   //  nothing!
Not(const FilterMatcherBase & arg1)185   Not(const FilterMatcherBase &arg1)
186       : FilterMatcherBase("Not"), arg1(arg1.copy()) {}
187 
Not(const boost::shared_ptr<FilterMatcherBase> & arg1)188   Not(const boost::shared_ptr<FilterMatcherBase> &arg1)
189       : FilterMatcherBase("Not"), arg1(arg1) {}
190 
Not(const Not & rhs)191   Not(const Not &rhs) : FilterMatcherBase(rhs), arg1(rhs.arg1) {}
192 
getName()193   virtual std::string getName() const {
194     return "(" + FilterMatcherBase::getName() + " " + getArgName(arg1) + ")";
195   }
196 
isValid()197   bool isValid() const { return arg1.get() && arg1->isValid(); }
198 
hasMatch(const ROMol & mol)199   bool hasMatch(const ROMol &mol) const {
200     PRECONDITION(isValid(), "FilterMatchOps::Not: arg1 is null");
201     return !arg1->hasMatch(mol);
202   }
203 
getMatches(const ROMol & mol,std::vector<FilterMatch> &)204   bool getMatches(const ROMol &mol, std::vector<FilterMatch> &) const {
205     PRECONDITION(isValid(), "FilterMatchOps::Not: arg1 is null");
206     // If we are a not, we really can't hold the match for
207     //  this query since by definition it won't exist!
208     std::vector<FilterMatch> matchVect;
209     return !arg1->getMatches(mol, matchVect);
210   }
211 
copy()212   boost::shared_ptr<FilterMatcherBase> copy() const {
213     return boost::shared_ptr<FilterMatcherBase>(new Not(*this));
214   }
215 
216  private:
217 #ifdef RDK_USE_BOOST_SERIALIZATION
218   friend class boost::serialization::access;
219   template <class Archive>
serialize(Archive & ar,const unsigned int version)220   void serialize(Archive &ar, const unsigned int version) {
221     RDUNUSED_PARAM(version);
222     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
223     ar &arg1;
224   }
225 #endif
226 };
227 }  // namespace FilterMatchOps
228 
229 RDKIT_FILTERCATALOG_EXPORT extern const char *SMARTS_MATCH_NAME_DEFAULT;
230 class RDKIT_FILTERCATALOG_EXPORT SmartsMatcher : public FilterMatcherBase {
231   ROMOL_SPTR d_pattern;
232   unsigned int d_min_count{0};
233   unsigned int d_max_count;
234 
235  public:
236   //! Construct a SmartsMatcher
237   SmartsMatcher(const std::string &name = SMARTS_MATCH_NAME_DEFAULT)
FilterMatcherBase(name)238       : FilterMatcherBase(name),
239         d_pattern(),
240 
241         d_max_count(UINT_MAX) {}
242 
243   //! Construct a SmartsMatcher from a query molecule
244   /*
245     \param pattern  query molecule used as the substructure search
246     \param unsigned int minCount  minimum number of times the pattern needs to
247     appear
248     \param maxCount the maximum number of times the pattern should appear
249     a value of UINT_MAX indicates the pattern can exist any number of times.
250     [default UINT_MAX]
251 
252   */
253   SmartsMatcher(const ROMol &pattern, unsigned int minCount = 1,
254                 unsigned int maxCount = UINT_MAX);
255 
256   //! Construct a SmartsMatcher
257   /*
258     \param name     name for the smarts pattern
259     \param pattern  query molecule used as the substructure search
260     \param unsigned int minCount  minimum number of times the pattern needs to
261     appear
262     \param maxCount the maximum number of times the pattern should appear
263     a value of UINT_MAX indicates the pattern can exist any number of times.
264     [default UINT_MAX]
265 
266   */
267 
268   SmartsMatcher(const std::string &name, const ROMol &pattern,
269                 unsigned int minCount = 1, unsigned int maxCount = UINT_MAX);
270 
271   //! Construct a SmartsMatcher from a smarts pattern
272   /*
273     \param name     name for the smarts pattern
274     \param smarts   smarts pattern to use for the filter
275     \param unsigned int minCount  minimum number of times the pattern needs to
276     appear
277     \param maxCount the maximum number of times the pattern should appear
278     a value of UINT_MAX indicates the pattern can exist any number of times.
279     [default UINT_MAX]
280   */
281 
282   SmartsMatcher(const std::string &name, const std::string &smarts,
283                 unsigned int minCount = 1, unsigned int maxCount = UINT_MAX);
284 
285   //! Construct a SmartsMatcher from a shared_ptr
286   /*
287     \param name     name for the smarts pattern
288     \param pattern  shared_ptr query molecule used as the substructure search
289     \param unsigned int minCount  minimum number of times the pattern needs to
290     appear
291     \param maxCount the maximum number of times the pattern should appear
292     a value of UINT_MAX indicates the pattern can exist any number of times.
293     [default UINT_MAX]
294   */
295 
296   SmartsMatcher(const std::string &name, ROMOL_SPTR onPattern,
297                 unsigned int minCount = 1, unsigned int maxCount = UINT_MAX);
298 
299   SmartsMatcher(const SmartsMatcher &rhs);
300 
301   //! Returns True if the Smarts pattern is valid
isValid()302   bool isValid() const { return d_pattern.get(); }
303 
304   //! Return the shared_ptr to the underlying query molecule
getPattern()305   const ROMOL_SPTR &getPattern() const { return d_pattern; }
306   //! Set the smarts pattern for the matcher
307   void setPattern(const std::string &smarts);
308   //! Set the query molecule for the matcher
309   void setPattern(const ROMol &mol);
310   //! Set the shared query molecule for the matcher
setPattern(const ROMOL_SPTR & pat)311   void setPattern(const ROMOL_SPTR &pat) { d_pattern = pat; }
312 
313   //! Get the minimum match count for the pattern to be true
getMinCount()314   unsigned int getMinCount() const { return d_min_count; }
315   //! Set the minimum match count for the pattern to be true
setMinCount(unsigned int val)316   void setMinCount(unsigned int val) { d_min_count = val; }
317   //! Get the maximum match count for the pattern to be true
getMaxCount()318   unsigned int getMaxCount() const { return d_max_count; }
319   //! Set the maximum match count for the pattern to be true
setMaxCount(unsigned int val)320   void setMaxCount(unsigned int val) { d_max_count = val; }
321 
322   virtual bool getMatches(const ROMol &mol,
323                           std::vector<FilterMatch> &matchVect) const;
324   virtual bool hasMatch(const ROMol &mol) const;
copy()325   virtual boost::shared_ptr<FilterMatcherBase> copy() const {
326     return boost::shared_ptr<FilterMatcherBase>(new SmartsMatcher(*this));
327   }
328 
329  private:
330 #ifdef RDK_USE_BOOST_SERIALIZATION
331   friend class boost::serialization::access;
332   template <class Archive>
save(Archive & ar,const unsigned int version)333   void save(Archive &ar, const unsigned int version) const {
334     RDUNUSED_PARAM(version);
335     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
336     std::string res;
337     MolPickler::pickleMol(*d_pattern.get(), res);
338     ar &res;
339     ar &d_min_count;
340     ar &d_max_count;
341   }
342   template <class Archive>
load(Archive & ar,const unsigned int version)343   void load(Archive &ar, const unsigned int version) {
344     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
345     {
346       RDUNUSED_PARAM(version);
347       std::string res;
348       ar &res;
349       d_pattern = boost::shared_ptr<ROMol>(new ROMol(res));
350     }
351     ar &d_min_count;
352     ar &d_max_count;
353   }
354   BOOST_SERIALIZATION_SPLIT_MEMBER();
355 #endif
356 };
357 
358 // ------------------------------------------------------------------
359 // Syntactic sugar for the following style patterns
360 // Add exclusion patterns
361 //   using FilterMatchOps;
362 //   And(new SmartsMatcher(pat1),
363 //                  new Not(SmartsMatcher(pat2)))
364 // The exclusion match never adds any FilterMatches when getMatches
365 //  is called, the main intent is for it to be used with an
366 //  And construct, such as:
367 //    And(SmartsMatcher(..), ExclusionList(...))
368 //
369 //  which will return the SmartsMatcher FilterMatch only if no patterns
370 //    in the exclusion list are found.
371 class RDKIT_FILTERCATALOG_EXPORT ExclusionList : public FilterMatcherBase {
372   std::vector<boost::shared_ptr<FilterMatcherBase>> d_offPatterns;
373 
374  public:
ExclusionList()375   ExclusionList() : FilterMatcherBase("Not any of"), d_offPatterns() {}
376 
377   //! Constructs an ExclusionList
378   //! true if non of the FilterMatcherBases are true
379   //! Syntactic sugar for
380   //!  using FilterMatchOps;
381   //!  And(Not(SmartsMatcher(pat1),
382   //!                 And(Not(SmartsMatcher(pat2)),
383   //!                                And(Not(Single...
384 
ExclusionList(const std::vector<boost::shared_ptr<FilterMatcherBase>> & offPatterns)385   ExclusionList(
386       const std::vector<boost::shared_ptr<FilterMatcherBase>> &offPatterns)
387       : FilterMatcherBase("Not any of"), d_offPatterns(offPatterns) {}
388 
getName()389   virtual std::string getName() const {
390     std::string res;
391     res = "(" + FilterMatcherBase::getName();
392     for (size_t i = 0; i < d_offPatterns.size(); ++i) {
393       res += " " + d_offPatterns[i]->getName();
394     }
395     res += ")";
396     return res;
397   }
398 
isValid()399   bool isValid() const {
400     for (size_t i = 0; i < d_offPatterns.size(); ++i)
401       if (!d_offPatterns[i]->isValid()) return false;
402     return true;
403   }
404 
addPattern(const FilterMatcherBase & base)405   void addPattern(const FilterMatcherBase &base) {
406     PRECONDITION(base.isValid(), "Invalid FilterMatcherBase");
407     d_offPatterns.push_back(base.copy());
408   }
409 
setExclusionPatterns(const std::vector<boost::shared_ptr<FilterMatcherBase>> & offPatterns)410   void setExclusionPatterns(
411       const std::vector<boost::shared_ptr<FilterMatcherBase>> &offPatterns) {
412     d_offPatterns = offPatterns;
413   }
414 
getMatches(const ROMol & mol,std::vector<FilterMatch> &)415   virtual bool getMatches(const ROMol &mol, std::vector<FilterMatch> &) const {
416     PRECONDITION(isValid(),
417                  "ExclusionList: one of the exclusion pattens is invalid");
418     bool result = true;
419     for (size_t i = 0; i < d_offPatterns.size() && result; ++i) {
420       result &= !d_offPatterns[i]->hasMatch(mol);
421     }
422 
423     return result;
424   }
425 
hasMatch(const ROMol & mol)426   virtual bool hasMatch(const ROMol &mol) const {
427     PRECONDITION(isValid(),
428                  "ExclusionList: one of the exclusion pattens is invalid");
429     bool result = true;
430     for (size_t i = 0; i < d_offPatterns.size() && result; ++i) {
431       result &= !d_offPatterns[i]->hasMatch(mol);
432     }
433 
434     return result;
435   }
436 
copy()437   virtual boost::shared_ptr<FilterMatcherBase> copy() const {
438     return boost::shared_ptr<FilterMatcherBase>(new ExclusionList(*this));
439   }
440 
441  private:
442 #ifdef RDK_USE_BOOST_SERIALIZATION
443   friend class boost::serialization::access;
444   template <class Archive>
serialize(Archive & ar,const unsigned int version)445   void serialize(Archive &ar, const unsigned int version) {
446     RDUNUSED_PARAM(version);
447     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
448     ar &d_offPatterns;
449   }
450 #endif
451 };
452 
453 class RDKIT_FILTERCATALOG_EXPORT FilterHierarchyMatcher
454     : public FilterMatcherBase {
455   std::vector<boost::shared_ptr<FilterHierarchyMatcher>> d_children;
456   boost::shared_ptr<FilterMatcherBase> d_matcher;
457 
458  public:
459   // !Default Constructor for serialization
FilterHierarchyMatcher()460   FilterHierarchyMatcher() : FilterMatcherBase(), d_matcher() {}
461   //! Constructs a FilterHierarchyMatcher from a FilterMatchBase
462   //!  A FilterHierarchyMatcher is a tree hierarchy where to
463   //!  match a child node, one needs to match the parent first.
464   //!  For each branch, the lowest nodes are returned when
465   //!   getting the filter matches.
466   /*
467       \param matcher FilterMatcherBase to match this node against
468   */
FilterHierarchyMatcher(const FilterMatcherBase & matcher)469   FilterHierarchyMatcher(const FilterMatcherBase &matcher)
470       : FilterMatcherBase(), d_matcher(matcher.copy()) {}
471 
472   //! Return the name for this node (from the underlying FilterMatcherBase)
getName()473   virtual std::string getName() const {
474     if (d_matcher.get()) {
475       return d_matcher->getName();
476     }
477     return "FilterMatcherHierarchy root";
478   }
479 
480   //! returns true if this node has a valid matcher
isValid()481   bool isValid() const { return d_matcher->isValid(); }
482 
483   //! Set a new FilterMatcherBase for this node
484   /*
485     \param matcher The new FilterMatcherBase
486   */
setPattern(const FilterMatcherBase & matcher)487   void setPattern(const FilterMatcherBase &matcher) {
488     PRECONDITION(matcher.isValid(), "Adding invalid patterns is not allowed.");
489     d_matcher = matcher.copy();
490     PRECONDITION(getName() == d_matcher->getName(), "Opps");
491   }
492 
493   //! add a FilterHierarchy as a child.
494   //!  returns the FilterHierarchy pointer used in the tree (this is a
495   //!   shallow copy of the original)
496   /*
497     \param hierarchy The new FilterHierarchyMatcher child for this node
498   */
addChild(const FilterHierarchyMatcher & hierarchy)499   boost::shared_ptr<FilterHierarchyMatcher> addChild(
500       const FilterHierarchyMatcher &hierarchy) {
501     PRECONDITION(hierarchy.d_matcher.get() && hierarchy.d_matcher->isValid(),
502                  "Only one root node is allowed in a FilterHierarchyMatcher");
503 
504     d_children.push_back(boost::shared_ptr<FilterHierarchyMatcher>(
505         new FilterHierarchyMatcher(hierarchy)));
506     return d_children.back();
507   }
508 
509   //! returns the FilterMatches against the given molecule
510   /*
511     \param mol The molecule to match against
512     \param matches The vector of FilterMatch objects that match
513   */
514   virtual bool getMatches(const ROMol &mol,
515                           std::vector<FilterMatch> &matches) const;
516 
517   //! Does this node match the molecule
518   /*
519     \param mol The molecule to match against
520   */
hasMatch(const ROMol & mol)521   virtual bool hasMatch(const ROMol &mol) const {
522     std::vector<FilterMatch> temp;
523     return getMatches(mol, temp);
524   }
525 
526   //! copys the FilterHierarchyMatcher into a FilterMatcherBase
copy()527   virtual boost::shared_ptr<FilterMatcherBase> copy() const {
528     return boost::shared_ptr<FilterMatcherBase>(
529         new FilterHierarchyMatcher(*this));
530   }
531 
532  private:
533 #ifdef RDK_USE_BOOST_SERIALIZATION
534   friend class boost::serialization::access;
535   template <class Archive>
serialize(Archive & ar,const unsigned int version)536   void serialize(Archive &ar, const unsigned int version) {
537     RDUNUSED_PARAM(version);
538     ar &boost::serialization::base_object<FilterMatcherBase>(*this);
539     ar &d_children;
540     ar &d_matcher;
541   }
542 #endif
543 };
544 
545 #ifdef RDK_USE_BOOST_SERIALIZATION
546 // Register all known filter matcher types for serialization
547 template <class Archive>
registerFilterMatcherTypes(Archive & ar)548 void registerFilterMatcherTypes(Archive &ar) {
549   ar.register_type(static_cast<FilterMatchOps::And *>(nullptr));
550   ar.register_type(static_cast<FilterMatchOps::Or *>(nullptr));
551   ar.register_type(static_cast<FilterMatchOps::Not *>(nullptr));
552   ar.register_type(static_cast<SmartsMatcher *>(nullptr));
553   ar.register_type(static_cast<ExclusionList *>(nullptr));
554   ar.register_type(static_cast<FilterHierarchyMatcher *>(nullptr));
555 }
556 #endif
557 }  // namespace RDKit
558 
559 #ifdef RDK_USE_BOOST_SERIALIZATION
560 BOOST_CLASS_VERSION(RDKit::SmartsMatcher, 1)
561 BOOST_CLASS_VERSION(RDKit::ExclusionList, 1)
562 BOOST_CLASS_VERSION(RDKit::FilterHierarchyMatcher, 1)
563 #endif
564 
565 #endif
566