File: QueryAtom.h

package info (click to toggle)
rdkit 202503.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 220,160 kB
  • sloc: cpp: 399,240; python: 77,453; ansic: 25,517; java: 8,173; javascript: 4,005; sql: 2,389; yacc: 1,565; lex: 1,263; cs: 1,081; makefile: 580; xml: 229; fortran: 183; sh: 105
file content (161 lines) | stat: -rw-r--r-- 5,042 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//
//  Copyright (C) 2001-2022 Greg Landrum and other RDKit contributors
//
//   @@ All Rights Reserved @@
//  This file is part of the RDKit.
//  The contents are covered by the terms of the BSD license
//  which is included in the file license.txt, found at the root
//  of the RDKit source tree.
//
#include <RDGeneral/export.h>
#ifndef RD_QUERYATOM_H
#define RD_QUERYATOM_H

#include <utility>
#include "Atom.h"
#include <Query/QueryObjects.h>
#include <GraphMol/QueryOps.h>

namespace RDKit {

//! Class for storing atomic queries
/*!
  QueryAtom objects are derived from Atom objects, so they can be
  added to molecules and the like, but they have much fancier
  querying capabilities.

 */
class RDKIT_GRAPHMOL_EXPORT QueryAtom : public Atom {
 public:
  typedef Queries::Query<int, Atom const *, true> QUERYATOM_QUERY;

  QueryAtom() : Atom() {}
  explicit QueryAtom(int num) : Atom(num), dp_query(makeAtomNumQuery(num)) {}
  explicit QueryAtom(const Atom &other)
      : Atom(other), dp_query(makeAtomNumQuery(other.getAtomicNum())) {
    if (other.getIsotope()) {
      this->expandQuery(makeAtomIsotopeQuery(other.getIsotope()),
                        Queries::CompositeQueryType::COMPOSITE_AND);
    }
    if (other.getFormalCharge()) {
      this->expandQuery(makeAtomFormalChargeQuery(other.getFormalCharge()),
                        Queries::CompositeQueryType::COMPOSITE_AND);
    }
    if (other.getNumRadicalElectrons()) {
      this->expandQuery(
          makeAtomNumRadicalElectronsQuery(other.getNumRadicalElectrons()),
          Queries::CompositeQueryType::COMPOSITE_AND);
    }
  }
  QueryAtom(const QueryAtom &other) : Atom(other) {
    if (other.dp_query) {
      dp_query = other.dp_query->copy();
    } else {
      dp_query = nullptr;
    }
  }
  QueryAtom &operator=(const QueryAtom &other) {
    if (this == &other) {
      return *this;
    }
    Atom::operator=(other);
    delete dp_query;
    if (other.dp_query) {
      dp_query = other.dp_query->copy();
    } else {
      dp_query = nullptr;
    }
    return *this;
  }

  QueryAtom(QueryAtom &&other) noexcept : Atom(std::move(other)) {
    dp_query = std::exchange(other.dp_query, nullptr);
  }
  QueryAtom &operator=(QueryAtom &&other) noexcept {
    if (this == &other) {
      return *this;
    }
    QueryAtom::operator=(std::move(other));
    dp_query = std::exchange(other.dp_query, nullptr);
    return *this;
  }

  ~QueryAtom() override;

  //! returns a copy of this query, owned by the caller
  Atom *copy() const override;

  // This method can be used to distinguish query atoms from standard atoms:
  bool hasQuery() const override { return dp_query != nullptr; }

  //! returns the label associated to this query
  std::string getQueryType() const override { return dp_query->getTypeLabel(); }

  //! replaces our current query with the value passed in
  void setQuery(QUERYATOM_QUERY *what) override {
    delete dp_query;
    dp_query = what;
  }
  //! returns our current query
  QUERYATOM_QUERY *getQuery() const override { return dp_query; }

  //! expands our current query
  /*!
    \param what          the Queries::Query to be added. The ownership of
                         the query is passed to the current object, where it
                         might be deleted, so that the pointer should not be
                         used again in the calling code.
    \param how           the operator to be used in the expansion
    \param maintainOrder (optional) flags whether the relative order of
                         the queries needs to be maintained, if this is
                         false, the order is reversed
    <b>Notes:</b>
      - \c what should probably be constructed using one of the functions
         defined in QueryOps.h
      - the \c maintainOrder option can be useful because the combination
        operators short circuit when possible.

  */
  void expandQuery(QUERYATOM_QUERY *what,
                   Queries::CompositeQueryType how = Queries::COMPOSITE_AND,
                   bool maintainOrder = true) override;

  //! returns true if we match Atom \c what
  bool Match(Atom const *what) const override;

  //! returns true if our query details match those of QueryAtom \c what
  bool QueryMatch(QueryAtom const *what) const;

 private:
  QUERYATOM_QUERY *dp_query{nullptr};

};  // end o' class

namespace detail {
inline std::string qhelper(const Atom::QUERYATOM_QUERY *q, unsigned int depth) {
  std::string res = "";
  if (q) {
    for (unsigned int i = 0; i < depth; ++i) {
      res += "  ";
    }
    res += q->getFullDescription() + "\n";
    for (const auto &child :
         boost::make_iterator_range(q->beginChildren(), q->endChildren())) {
      res += qhelper(child.get(), depth + 1);
    }
  }
  return res;
}
}  // namespace detail
inline std::string describeQuery(const Atom *atom) {
  PRECONDITION(atom, "bad atom");
  std::string res = "";
  if (atom->hasQuery()) {
    res = detail::qhelper(atom->getQuery(), 0);
  }
  return res;
}

};  // namespace RDKit

#endif