FindMany.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_FindMany_h
2 #define canvas_Persistency_Common_FindMany_h
3 ////////////////////////////////////////////////////////////////////////
4 // FindMany
5 //
6 // A smart query object used as the main way of accessing associated
7 // objects in an association (one-to-one, one-to-many or many-to-many).
8 //
9 // Given an Assns associating A with B (or B with A) (possibly with an
10 // associated data object D) and a source ACOLL of A objects to be found
11 // in the Assns, allow indexed access to the B and/or D objects
12 // associated with the A objects in ACOLL.
13 //
14 ////////////////////////////////////
15 // Interface.
16 //////////
17 //
18 // For ease of understanding, the interface is presented here; reading
19 // the rest of the header is not for the faint of heart. Compare with
20 // the corresponding interface for FindOne.
21 //
22 // Notes:
23 //
24 // * ProdB and Data are the only template arguments that must be
25 // specified when constructing a FindMany. Any other items
26 // are deducible from arguments.
27 //
28 // * The FindMany needs a source of objects of type A, a
29 // data container (e.g. an event) and an input tag corresponding to
30 // the underlying association collection from which to create itself.
31 //
32 // * When constructed, the FindMany will obtain and
33 // interrogate the correct Assns and provide access to the B (and/or D)
34 // object(s) associated with each supplied A object in the order in
35 // which the A objects were specified.
36 //
37 // * If the specified A does not have an associated B or D then the
38 // vector will be empty.
39 //
40 // * If the required association collection has an extra data object D
41 // with each association then it *must* be specified as a template
42 // argument, even if it is not relevant to the current query.
43 //
44 // * *All* indexed accessors (at(), data(), get()) are
45 // bounds-checked. Note that, because of the possible one-to-many
46 // association, these functions all return (or take as a reference in
47 // the case of get()) vectors, viz:
48 // * at() returns a const reference to a vector of const* (FindMany)
49 // or Ptr (FindManyP).
50 // * data returns a const reference to a vector of data objects.
51 // * get() takes references to a vector of const* or Ptr as
52 // appropriate, and a vector of data objects (if the data type is not
53 // void).
54 //
55 // Useful type aliases.
56 //
57 // using assoc_t = ProdB;
58 // using data_t = Data;
59 // using value_type = std::vector<assoc_t const*>; // FindMany
60 // using value_type = std::vector<art::Ptr<assoc_t>>; // FindManyP
61 // using size_type = typename std::vector<value_type>::size_type;
62 // using const_reference = value_type const&;
63 // using reference = value_type&;
64 // using data_const_reference = typename std::vector<data_t const*> const&;
65 // using data_reference = typename std::vector<data_t const*>&;
66 //
67 // Constructors.
68 //
69 // // From Handle or ValidHandle to collection of A.
70 // FindMany<ProdB>(Handle<ProdAColl> const&,
71 // DataContainer const&,
72 // InputTag const&);
73 // FindMany<ProdB, Data>(Handle<ProdAColl> const&,
74 // DataContainer const&,
75 // InputTag const&);
76 //
77 // // From sequence of pointer to A (including View<A>).
78 // FindMany<ProdB>(View<ProdA> const&,
79 // DataContainer const&,
80 // InputTag const&);
81 // FindMany<ProdB, Data>(View<ProdA> const&,
82 // DataContainer const&,
83 // InputTag const&);
84 //
85 // // From arbitrary sequence of Ptr<A>.
86 // FindMany<ProdB>(PtrProdAColl const&,
87 // DataContainer const&,
88 // InputTag const&);
89 // FindMany<ProdB, Data>(PtrProdAColl const&,
90 // DataContainer const&,
91 // InputTag const&);
92 //
93 // // From an initializer list of Ptr<A>.
94 // FindMany<ProdB>(<brace-enclosed initializer list>,
95 // DataContainer const&,
96 // InputTag const&);
97 // FindMany<ProdB, Data>(<brace-enclosed initializer list>,
98 // DataContainer const&,
99 // InputTag const&);
100 //
101 // Modifiers.
102 //
103 // <NONE>.
104 //
105 // Accessors.
106 //
107 // size_type size() const;
108 // const_reference at(size_type) const;
109 // const_data_reference data(size_type) const;
110 // size_type get(size_type,
111 // reference)
112 // const; // Returns number of elements appended.
113 // size_type get(size_type,
114 // reference,
115 // data_reference)
116 // const; // *Must* be used for FindMany<ProdB, Data>.
117 //
118 // Comparison operations.
119 //
120 // bool operator == (FindMany const& other) const;
121 //
122 ////////////////////////////////////////////////////////////////////////
123 
129 #include "cetlib/maybe_ref.h"
130 
131 #include <initializer_list>
132 #include <vector>
133 
134 /* #undef ART_IPR_BY_PTR */
135 
136 namespace art {
137  // General template
138  template <typename ProdB, typename DATA = void>
139  class FindMany;
140 
141  // Specialization.
142  template <typename ProdB>
143  class FindMany<ProdB, void>;
144 }
145 
146 ////////////////////////////////////////////////////////////////////////
147 // Implementation of the specialization.
148 template <typename ProdB>
149 class art::FindMany<ProdB, void> {
150 public:
151 #ifdef ART_IPR_BY_PTR
152  using bColl_t = std::vector<std::vector<Ptr<ProdB> > >;
153 #else
154  using bColl_t = std::vector<std::vector<ProdB const*> >;
155 #endif
156  using value_type = typename bColl_t::value_type;
157  using size_type = typename bColl_t::size_type;
158  using difference_type = typename bColl_t::difference_type;
159  using const_reference = typename bColl_t::const_reference;
160  using reference = typename bColl_t::reference;
161 
162  using assoc_t = ProdB;
163 
164  template <typename Handle, typename DataContainer, typename Tag>
165  FindMany(Handle const& aCollection,
166  DataContainer const& dc,
167  Tag const& tag,
168  std::enable_if_t<detail::is_handle<Handle>::value>* = nullptr);
169 
170  template <typename ProdAColl, typename DataContainer, typename Tag>
171  FindMany(ProdAColl const& view,
172  DataContainer const& dc,
173  Tag const& tag,
174  std::enable_if_t<std::is_pointer<typename ProdAColl::value_type>::value>* = nullptr);
175 
176  template <typename PtrProdAColl, typename DataContainer, typename Tag>
177  FindMany(PtrProdAColl const& aPtrColl,
178  DataContainer const& dc,
179  Tag const& tag,
180  std::enable_if_t<std::is_same<typename PtrProdAColl::value_type,
182 
183  template <typename ProdA, typename DataContainer, typename Tag>
184  FindMany(std::initializer_list<Ptr<ProdA> > const& ptrs,
185  DataContainer const& dc,
186  Tag const& tag);
187 
188  // Is this a valid query (did we find an Assns)?
189  bool isValid() const;
190 
191  // Number of query results
192  size_type size() const;
193 
194  // Associated item by index (bounds-checked).
195  const_reference at(size_type i) const;
196 
197  size_type get(size_type i, reference item) const;
198 
199  bool operator == (FindMany<ProdB, void> const& other) const;
200 
201 protected:
202  FindMany() = default;
203  bColl_t& bCollection() { return bCollection_; }
204 
205  void setStoredException(std::shared_ptr<art::Exception const>&& e);
206  void throwIfInvalid() const;
207 
208 private:
209  bColl_t bCollection_{};
210  std::shared_ptr<art::Exception const> storedException_{nullptr};
211 };
212 
213 template <typename ProdB, typename Data>
214 class art::FindMany : private art::FindMany<ProdB, void> {
215 private:
217 public:
218  using dataColl_t = std::vector<std::vector<Data const*> >;
219  using value_type = typename base::value_type;
220  using size_type = typename base::size_type;
223  using reference = typename base::reference;
224  using assoc_t = typename base::assoc_t;
225 
226  using data_const_pointer = typename dataColl_t::const_pointer;
227  using data_const_reference = typename dataColl_t::const_reference;
228  using data_reference = typename dataColl_t::reference;
229 
230  using data_t = Data;
231 
232  template <typename Handle, typename DataContainer, typename Tag>
233  FindMany(Handle const& aCollection,
234  DataContainer const& dc,
235  Tag const& tag,
236  std::enable_if_t<detail::is_handle<Handle>::value>* = nullptr);
237 
238  template <typename ProdAColl, typename DataContainer, typename Tag>
239  FindMany(ProdAColl const& view,
240  DataContainer const& dc,
241  Tag const& tag,
242  std::enable_if_t<std::is_pointer<typename ProdAColl::value_type>::value>* = nullptr);
243 
244  template <typename PtrProdAColl, typename DataContainer, typename Tag>
245  FindMany(PtrProdAColl const& aPtrColl,
246  DataContainer const& dc,
247  Tag const& tag,
248  std::enable_if_t<std::is_same<typename PtrProdAColl::value_type,
250 
251  template <typename ProdA, typename DataContainer, typename Tag>
252  FindMany(std::initializer_list<Ptr<ProdA> > const& ptrs,
253  DataContainer const& dc,
254  Tag const& tag);
255 
256  using base::size;
257  using base::isValid;
258  using base::at;
259  using base::get;
260 
261  // Association extra-data object by index (bounds-checked).
263 
264  // Associated item and extra-data object by index (bounds-checked).
265  size_type get(size_type i, reference item, data_reference data) const;
266 
267  bool operator == (FindMany<ProdB, Data> const& other) const;
268 
269 private:
271 };
272 
273 ////////////////////////////////////////////////////////////////////////
274 // Base class implementation.
275 template <typename ProdB>
276 template <typename Handle, typename DataContainer, typename Tag>
278 FindMany(Handle const& aCollection,
279  DataContainer const& dc,
280  Tag const& tag,
281  std::enable_if_t<detail::is_handle<Handle>::value>*)
282 {
283  using ProdA = typename Handle::element_type::value_type;
285  storedException_ = finder(*aCollection, bCollection_);
286 }
287 
288 template <typename ProdB>
289 template <typename ProdAColl, typename DataContainer, typename Tag>
291 FindMany(ProdAColl const& view,
292  DataContainer const& dc,
293  Tag const& tag,
295 {
296  using ProdA = std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
298  storedException_ = finder(view, bCollection_);
299 }
300 
301 template <typename ProdB>
302 template <typename PtrProdAColl, typename DataContainer, typename Tag>
304 FindMany(PtrProdAColl const& aPtrColl,
305  DataContainer const& dc,
306  Tag const& tag,
307  std::enable_if_t<std::is_same<typename PtrProdAColl::value_type,
309 {
310  using ProdA = typename PtrProdAColl::value_type::value_type;
312  storedException_ = finder(aPtrColl, bCollection_);
313 }
314 
315 template <typename ProdB>
316 template <typename ProdA, typename DataContainer, typename Tag>
318 FindMany(std::initializer_list<Ptr<ProdA> > const& ptrs,
319  DataContainer const& dc,
320  Tag const& tag)
321 {
323  storedException_ = finder(ptrs, bCollection_);
324 }
325 
326 template <typename ProdB>
327 inline
328 auto
331  -> size_type
332 {
333  throwIfInvalid();
334  return bCollection_.size();
335 }
336 
337 template <typename ProdB>
338 inline
339 bool
341 isValid() const
342 {
343  return (storedException_.get() == nullptr);
344 }
345 
346 template <typename ProdB>
347 inline
348 auto
350 at(size_type const i) const
351  -> const_reference
352 {
353  throwIfInvalid();
354  return bCollection_.at(i);
355 }
356 
357 template <typename ProdB>
358 inline
359 auto
361 get(size_type const i, reference item) const
362  -> size_type
363 {
364  throwIfInvalid();
365  const_reference ref(bCollection_.at(i));
366  item.insert(item.end(), ref.begin(), ref.end());
367  return ref.size();
368 }
369 
370 template <typename ProdB>
371 inline
372 bool
375 {
376  throwIfInvalid();
377  return bCollection_ == other.bCollection_;
378 }
379 
380 template <typename ProdB>
381 inline
382 void
384 setStoredException(std::shared_ptr<art::Exception const>&& e)
385 {
386  storedException_ = std::move(e);
387 }
388 
389 template <typename ProdB>
390 inline
391 void
394 {
395  if (!isValid()) {
396  throw Exception(errors::LogicError, "Invalid FindMany", *storedException_)
397  << "Attempt to use a FindMany where the underlying art::Assns product was not found.";
398  }
399 }
400 
401 ////////////////////////////////////////////////////////////////////////
402 // Derived class implementation.
403 template <typename ProdB, typename Data>
404 template <typename Handle, typename DataContainer, typename Tag>
406 FindMany(Handle const& aCollection,
407  DataContainer const& dc,
408  Tag const& tag,
409  std::enable_if_t<detail::is_handle<Handle>::value>*)
410 {
411  using ProdA = typename Handle::element_type::value_type;
414 }
415 
416 template <typename ProdB, typename Data>
417 template <typename ProdAColl, typename DataContainer, typename Tag>
419 FindMany(ProdAColl const& view,
420  DataContainer const& dc,
421  Tag const& tag,
423 {
424  using ProdA = std::remove_const_t<std::remove_pointer_t<typename ProdAColl::value_type>>;
427 }
428 
429 template <typename ProdB, typename Data>
430 template <typename PtrProdAColl, typename DataContainer, typename Tag>
432 FindMany(PtrProdAColl const& aPtrColl,
433  DataContainer const& dc,
434  Tag const& tag,
435  std::enable_if_t<std::is_same<typename PtrProdAColl::value_type,
437 {
438  using ProdA = typename PtrProdAColl::value_type::value_type;
441 }
442 
443 template <typename ProdB, typename Data>
444 template <typename ProdA, typename DataContainer, typename Tag>
446 FindMany(std::initializer_list<Ptr<ProdA> > const& ptrs,
447  DataContainer const& dc,
448  Tag const& tag)
449 {
452 }
453 
454 template <typename ProdB, typename Data>
455 inline
456 auto
458 data(size_type const i) const
460 {
462  return dataCollection_.at(i);
463 }
464 
465 template <typename ProdB, typename Data>
466 inline
467 auto
470  -> size_type
471 {
472  size_type result = base::get(i, item); // Will check validity.
474  data.insert(data.end(), ref.begin(), ref.end());;
475  return result;
476 }
477 
478 template <typename ProdB, typename Data>
479 inline
480 bool
483 {
484  return this->base::operator==(other) && // Will check validity.
486 }
487 
488 #undef ART_IPR_BY_PTR
489 
490 #endif /* canvas_Persistency_Common_FindMany_h */
491 
492 // Local Variables:
493 // mode: c++
494 // End:
typename base::const_reference const_reference
Definition: FindMany.h:222
InputTag input_tag(InputTag const &tag)
Definition: IPRHelper.h:21
size_type get(size_type i, reference item) const
Definition: FindMany.h:361
typename base::assoc_t assoc_t
Definition: FindMany.h:224
typename dataColl_t::const_pointer data_const_pointer
Definition: FindMany.h:226
size_type size() const
Definition: FindMany.h:330
size_type get(size_type i, reference item, data_reference data) const
Definition: FindMany.h:469
typename base::reference reference
Definition: FindMany.h:223
typename bColl_t::size_type size_type
Definition: FindMany.h:157
typename bColl_t::difference_type difference_type
Definition: FindMany.h:158
bool operator==(FindMany< ProdB, Data > const &other) const
Definition: FindMany.h:482
typename dataColl_t::reference data_reference
Definition: FindMany.h:228
const XML_Char const XML_Char * data
Definition: expat.h:268
dataColl_t dataCollection_
Definition: FindMany.h:270
typename base::size_type size_type
Definition: FindMany.h:220
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Definition: typedefs.hpp:11
typename bColl_t::reference reference
Definition: FindMany.h:160
const XML_Char int const XML_Char * value
Definition: expat.h:331
std::vector< std::vector< Data const * > > dataColl_t
Definition: FindMany.h:218
bool operator==(FindMany< ProdB, void > const &other) const
Definition: FindMany.h:374
typename bColl_t::const_reference const_reference
Definition: FindMany.h:159
typename base::difference_type difference_type
Definition: FindMany.h:221
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void setStoredException(std::shared_ptr< art::Exception const > &&e)
Definition: FindMany.h:384
typename base::value_type value_type
Definition: FindMany.h:219
std::vector< std::vector< ProdB const * > > bColl_t
Definition: FindMany.h:154
typename bColl_t::value_type value_type
Definition: FindMany.h:156
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
void throwIfInvalid() const
Definition: FindMany.h:393
Float_t e
Definition: plot.C:35
const_reference at(size_type i) const
Definition: FindMany.h:350
typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData
FindMany(Handle const &aCollection, DataContainer const &dc, Tag const &tag, std::enable_if_t< detail::is_handle< Handle >::value > *=nullptr)
Definition: FindMany.h:406
Definition: fwd.h:28
data_const_reference data(size_type i) const
Definition: FindMany.h:458
typename dataColl_t::const_reference data_const_reference
Definition: FindMany.h:227