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_CATALOG_H__
34 #define __RD_FILTER_CATALOG_H__
35 
36 #include <RDGeneral/types.h>  // For Dict
37 #include <GraphMol/RDKitBase.h>
38 #include <GraphMol/Substruct/SubstructMatch.h>
39 #include <Catalogs/CatalogEntry.h>
40 
41 #ifdef RDK_USE_BOOST_SERIALIZATION
42 #include <RDGeneral/BoostStartInclude.h>
43 #include <boost/archive/text_oarchive.hpp>
44 #include <boost/archive/text_iarchive.hpp>
45 #include <boost/serialization/vector.hpp>
46 #include <boost/serialization/shared_ptr.hpp>
47 #include <RDGeneral/BoostEndInclude.h>
48 #endif
49 
50 #include "FilterMatchers.h"
51 
52 namespace RDKit {
53 typedef std::map<std::string, std::string> STRING_PROPS;
54 
55 class RDKIT_FILTERCATALOG_EXPORT FilterCatalogEntry
56     : public RDCatalog::CatalogEntry {
57  private:
58   boost::shared_ptr<FilterMatcherBase> d_matcher;
59   Dict d_props;
60 
61  public:
FilterCatalogEntry()62   FilterCatalogEntry() : d_matcher(), d_props() {}
63 
FilterCatalogEntry(const std::string & name,const FilterMatcherBase & matcher)64   FilterCatalogEntry(const std::string &name, const FilterMatcherBase &matcher)
65       : RDCatalog::CatalogEntry(), d_matcher(matcher.copy()) {
66     setDescription(name);
67   }
68 
FilterCatalogEntry(const std::string & name,boost::shared_ptr<FilterMatcherBase> matcher)69   FilterCatalogEntry(const std::string &name,
70                      boost::shared_ptr<FilterMatcherBase> matcher)
71       : RDCatalog::CatalogEntry(), d_matcher(matcher) {
72     setDescription(name);
73   }
74 
FilterCatalogEntry(const FilterCatalogEntry & rhs)75   FilterCatalogEntry(const FilterCatalogEntry &rhs)
76       : RDCatalog::CatalogEntry(rhs),
77         d_matcher(rhs.d_matcher),
78         d_props(rhs.d_props) {}
79 
~FilterCatalogEntry()80   virtual ~FilterCatalogEntry() {}
81 
82   //------------------------------------
83   //! Returns true if the Filters stored in this catalog entry are valid
84 
isValid()85   bool isValid() const { return d_matcher.get() && d_matcher->isValid(); }
86 
87   //------------------------------------
88   //! Returns the description of the catalog entry
89   std::string getDescription() const;
90 
91   //------------------------------------
92   //! Sets the description of the catalog entry
93   /*
94     \param const std::string & description
95    */
96   void setDescription(const std::string &description);
97 
98   //! \name Properties
99   //@{
100 
101   //! returns a list with the names of our \c properties
getPropList()102   STR_VECT getPropList() const { return d_props.keys(); }
103 
104   //! sets a \c property value
105   /*!
106      \param key the name under which the \c property should be stored.
107          If a \c property is already stored under this name, it will be
108          replaced.
109      \param val the value to be stored
110    */
111   template <typename T>
setProp(const char * key,T val)112   void setProp(const char *key, T val) {
113     std::string what(key);
114     setProp(what, val);
115   }
116   //! \overload
117   template <typename T>
setProp(const std::string & key,T val)118   void setProp(const std::string &key, T val) {
119     d_props.setVal(key, val);
120   }
121 
122   //! allows retrieval of a particular property value
123   /*!
124 
125      \param key the name under which the \c property should be stored.
126          If a \c property is already stored under this name, it will be
127          replaced.
128      \param res a reference to the storage location for the value.
129 
130      <b>Notes:</b>
131        - if no \c property with name \c key exists, a KeyErrorException will be
132      thrown.
133        - the \c boost::lexical_cast machinery is used to attempt type
134      conversions.
135          If this fails, a \c boost::bad_lexical_cast exception will be thrown.
136 
137   */
138   template <typename T>
getProp(const char * key,T & res)139   void getProp(const char *key, T &res) const {
140     d_props.getVal(key, res);
141   }
142   //! \overload
143   template <typename T>
getProp(const std::string & key,T & res)144   void getProp(const std::string &key, T &res) const {
145     d_props.getVal(key, res);
146   }
147   //! \overload
148   template <typename T>
getProp(const char * key)149   T getProp(const char *key) const {
150     return d_props.getVal<T>(key);
151   }
152   //! \overload
153   template <typename T>
getProp(const std::string & key)154   T getProp(const std::string &key) const {
155     return d_props.getVal<T>(key);
156   }
157 
158   //! returns whether or not we have a \c property with name \c key
159   //!  and assigns the value if we do
160   template <typename T>
getPropIfPresent(const char * key,T & res)161   bool getPropIfPresent(const char *key, T &res) const {
162     return d_props.getValIfPresent(key, res);
163   }
164   //! \overload
165   template <typename T>
getPropIfPresent(const std::string & key,T & res)166   bool getPropIfPresent(const std::string &key, T &res) const {
167     return d_props.getValIfPresent(key, res);
168   }
169 
170   //! returns whether or not we have a \c property with name \c key
hasProp(const char * key)171   bool hasProp(const char *key) const { return d_props.hasVal(key); }
172   //! \overload
hasProp(const std::string & key)173   bool hasProp(const std::string &key) const {
174     return d_props.hasVal(key);
175     // return hasProp(key.c_str());
176   }
177 
178   //! clears the value of a \c property
clearProp(const char * key)179   void clearProp(const char *key) {
180     std::string what(key);
181     clearProp(what);
182   };
183   //! \overload
clearProp(const std::string & key)184   void clearProp(const std::string &key) { d_props.clearVal(key); };
185 
186   // -------------------------------------------
187   //!  Properties usually contain the reference and source
188   //!  for the catalog entry.
189 
getProps()190   Dict &getProps() { return d_props; }
getProps()191   const Dict &getProps() const { return d_props; }
setProps(const Dict & props)192   void setProps(const Dict &props) { d_props = props; }
193 
194   //------------------------------------
195   //! Returns the matching filters for this catalog entry
196   /*
197     \param mol The molecule to match against
198     \param std::vector<FilterMatch> the resulting FilterMatches
199    */
getFilterMatches(const ROMol & mol,std::vector<FilterMatch> & matchVect)200   bool getFilterMatches(const ROMol &mol,
201                         std::vector<FilterMatch> &matchVect) const {
202     return this->isValid() && d_matcher->getMatches(mol, matchVect);
203   }
204 
205   //------------------------------------
206   //! Returns true if the filters in this catalog entry match the molecule
207   /*
208     \param mol The molecule to match against
209    */
210 
hasFilterMatch(const ROMol & mol)211   bool hasFilterMatch(const ROMol &mol) const {
212     return this->isValid() && d_matcher->hasMatch(mol);
213   }
214 
215   //! serializes (pickles) to a stream
216   virtual void toStream(std::ostream &ss) const;
217   //! returns a string with a serialized (pickled) representation
218   virtual std::string Serialize() const;
219   //! initializes from a stream pickle
220   virtual void initFromStream(std::istream &ss);
221   //! initializes from a string pickle
222   virtual void initFromString(const std::string &text);
223 
224  private:
225 #ifdef RDK_USE_BOOST_SERIALIZATION
226   friend class boost::serialization::access;
227   template <class Archive>
save(Archive & ar,const unsigned int version)228   void save(Archive &ar, const unsigned int version) const {
229     RDUNUSED_PARAM(version);
230     registerFilterMatcherTypes(ar);
231 
232     ar &d_matcher;
233     // we only save string based props here...
234     STR_VECT keys = d_props.keys();
235     std::vector<std::string> string_props;
236     for (size_t i = 0; i < keys.size(); ++i) {
237       std::string val;
238       try {
239         if (d_props.getValIfPresent<std::string>(keys[i], val)) {
240           string_props.push_back(keys[i]);
241           string_props.push_back(val);
242         }
243       } catch (const boost::bad_any_cast &) {
244         // pass, can't serialize
245         // warning, this changes properties types, see Dict.cpp
246       }
247     }
248     ar &string_props;
249   }
250 
251   template <class Archive>
load(Archive & ar,const unsigned int version)252   void load(Archive &ar, const unsigned int version) {
253     RDUNUSED_PARAM(version);
254     registerFilterMatcherTypes(ar);
255 
256     ar &d_matcher;
257     std::vector<std::string> string_props;
258     ar &string_props;
259     d_props.reset();
260 
261     for (size_t i = 0; i < string_props.size() / 2; ++i) {
262       d_props.setVal(string_props[i * 2], string_props[i * 2 + 1]);
263     }
264   }
265 
266   BOOST_SERIALIZATION_SPLIT_MEMBER();
267 #endif
268 };
269 }  // namespace RDKit
270 
271 #ifdef RDK_USE_BOOST_SERIALIZATION
272 BOOST_CLASS_VERSION(RDKit::FilterCatalogEntry, 1);
273 #endif
274 
275 #endif  //__RD_FILTER_CATALOG_H__
276