LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
IPRHelper.h
Go to the documentation of this file.
1 #ifndef canvas_Persistency_Common_detail_IPRHelper_h
2 #define canvas_Persistency_Common_detail_IPRHelper_h
3 
4 // Helper class and associated gubbins for populating the FindOne and
5 // FindMany query objects for inter-product references.
6 
13 
14 #include <type_traits>
15 #include <unordered_map>
16 
17 namespace art {
18  namespace detail {
19 
20  inline InputTag
21  input_tag(InputTag const& tag)
22  {
23  return tag;
24  }
25 
26  template <typename T>
27  inline InputTag
28  input_tag(ProductToken<T> const& token)
29  {
30  return token.inputTag_;
31  }
32 
33  template <typename T>
34  inline InputTag
35  input_tag(ViewToken<T> const& token)
36  {
37  return token.inputTag_;
38  }
39 
40  class IPRHelperDef {
41  };
42 
43  template <typename ProdA,
44  typename ProdB,
45  typename Data,
46  typename DATACOLL,
47  typename EVENT>
48  class IPRHelper;
49 
50  template <typename DATA>
52  public:
53  void init(size_t size, std::vector<DATA const*>& data) const;
54  template <typename ASSNS>
55  void fill(ptrdiff_t assns_index,
56  ASSNS const& assns,
57  size_t data_index,
58  std::vector<DATA const*>& data) const;
59 
60  void init(size_t size, std::vector<std::vector<DATA const*>>& data) const;
61  template <typename ASSNS>
62  void fill(ptrdiff_t assns_index,
63  ASSNS const& assns,
64  size_t data_index,
65  std::vector<std::vector<DATA const*>>& data) const;
66 
67  void init(size_t, IPRHelperDef&) const;
68  template <typename ASSNS>
69  void fill(ptrdiff_t, ASSNS const&, size_t, IPRHelperDef&) const;
70  };
71 
72  // Note that the template parameter Bcoll is determined by the
73  // IPRHelper's use by the FindOne and FindMany classes, and is not
74  // as free-ranging as one might naively imagine.
75  template <typename ProdB>
76  class BcollHelper {
77  public:
78  BcollHelper(InputTag const& assnsTag);
79  template <typename Bcoll>
80  void init(size_t size, Bcoll& bColl);
81 
82  // 1. When Bcoll is a collection of pointer to const B -- one to one.
83  template <typename Bcoll>
84  std::enable_if_t<
86  fill(size_t index, Ptr<ProdB> const& item, Bcoll& bColl);
87 
88  // 2. When Bcoll is a collection of Ptr<B> -- one to one.
89  template <typename Bcoll>
90  std::enable_if_t<
91  std::is_convertible<typename Bcoll::value_type, Ptr<ProdB>>::value>
92  fill(size_t index, Ptr<ProdB> const& item, Bcoll& bColl);
93 
94  template <typename Bcoll>
95  void init(size_t size, std::vector<Bcoll>& bColls) const;
96 
97  // 3. When Bcoll is a collection of pointer to const B -- one to many.
98  template <typename Bcoll>
99  std::enable_if_t<
101  fill(size_t index,
102  Ptr<ProdB> const& item,
103  std::vector<Bcoll>& bColls) const;
104 
105  // 4. When Bcoll is a collection of Ptr<B> -- one to many.
106  template <typename Bcoll>
107  std::enable_if_t<
108  std::is_convertible<typename Bcoll::value_type, Ptr<ProdB>>::value>
109  fill(size_t index,
110  Ptr<ProdB> const& item,
111  std::vector<Bcoll>& bColls) const;
112 
113  private:
115  std::vector<uint8_t> seen_;
116  };
117  }
118 }
119 
120 template <typename ProdA,
121  typename ProdB,
122  typename Data,
123  typename DATACOLL,
124  typename EVENT>
126 private:
127  // We use IPRHelperDef in place of DATACOLL if Data is void.
130 
131 public:
132  typedef std::shared_ptr<art::Exception const> shared_exception_t;
133 
134  IPRHelper(EVENT const& e, InputTag const& tag) : event_(e), assnsTag_(tag) {}
135 
136  // template <typename A, typename B> shared_exception_t operator()(A const& a,
137  // B const& b) const
138  // (1) fills in b, and
139  // (2) returns a (shared pointer to) an exception. The pointer is
140  // non-null on failure. Note that the returned 'b' might be empty.
141  //
142  // 1. When dColl not wanted.
143  template <typename Acoll, typename Bcoll>
144  shared_exception_t operator()(Acoll const& aColl, Bcoll& bColl) const;
145 
146  // 2. Algorithm useful when dealing with collections of Ptrs.
147  template <typename Acoll, typename Bcoll>
148  shared_exception_t operator()(Acoll const& aColl,
149  Bcoll& bColl,
150  dataColl_t& dColl) const;
151 
152 private:
153  EVENT const& event_;
155 };
156 
157 // 1.
158 template <typename ProdA,
159  typename ProdB,
160  typename Data,
161  typename DATACOLL,
162  typename EVENT>
163 template <typename Acoll, typename Bcoll>
164 inline auto
166  Acoll const& aColl,
167  Bcoll& bColl) const -> shared_exception_t
168 {
169  IPRHelperDef dummy;
170  return (*this)(aColl, bColl, dummy);
171 }
172 
173 // 2.
175 // Implementation notes.
176 //
177 // The current implementation does not verify the that ProductID of the
178 // item in the association collection matches that of the item in the
179 // reference collection before attempting to dereference its Ptr
180 // (although it does verify ptr.isAvailable()). This means that in the
181 // case where an association collection refers to multiple available
182 // AProd collections, all of those collections will be read from file
183 // even if the reference collection does not include items from one or
184 // more of those AProd collections.
185 //
186 // If one were to provide an implementation that did this, one would
187 // change the unordered_multimap to key on the full ptr instead of the
188 // pointer. There is a specialization of std::hash<T> for T =
189 // art::Ptr<X> to support this.
190 //
191 // However, it would be problematic to do the lookup if the reference
192 // item was not in fact a Ptr. Maybe it would be relatively efficient if
193 // one were able to do a lookup in the table against an entity not a Ptr
194 // for which I could write a comparison function that compared the
195 // ProductID and only if they matched, the pointer with suitable get().
196 //
197 // For now however, no-one has requested this,
199 template <typename ProdA,
200  typename ProdB,
201  typename Data,
202  typename DATACOLL,
203  typename EVENT>
204 template <typename Acoll, typename Bcoll>
205 auto
207 operator()(Acoll const& aColl, Bcoll& bColl, dataColl_t& dColl) const
209 {
210  detail::BcollHelper<ProdB> bh(assnsTag_);
212  typename EVENT::template HandleT<Assns<ProdA, ProdB, Data>> assnsHandle;
213  event_.getByLabel(assnsTag_, assnsHandle);
214  if (!assnsHandle.isValid()) {
215  return assnsHandle.whyFailed(); // Failed to get Assns product.
216  }
217  bh.init(aColl.size(), bColl);
218  dh.init(aColl.size(), dColl);
219  // Answer cache.
220  std::unordered_multimap<typename Ptr<ProdA>::const_pointer,
221  std::pair<Ptr<ProdB>, ptrdiff_t>>
222  lookupCache;
223  ptrdiff_t counter{0};
224  for (auto const& apair : *assnsHandle) {
225  if (apair.first.isAvailable()) {
226  lookupCache.emplace(
227  apair.first.get(),
228  typename decltype(lookupCache)::mapped_type(apair.second, counter));
229  }
230  ++counter;
231  }
232  // Now use the cache.
233  size_t bIndex{0};
234  for (typename Acoll::const_iterator i = aColl.begin(), e = aColl.end();
235  i != e;
236  ++i, ++bIndex) {
237  auto foundItems = lookupCache.equal_range(
239  if (foundItems.first != lookupCache.cend()) {
240  std::for_each(
241  foundItems.first,
242  foundItems.second,
243  [&bh, &dh, &bColl, bIndex, &assnsHandle, &dColl](
244  typename decltype(lookupCache)::const_reference itemPair) {
245  bh.fill(bIndex, itemPair.second.first, bColl);
246  dh.fill(itemPair.second.second, *assnsHandle, bIndex, dColl);
247  });
248  }
249  }
250  return shared_exception_t();
251 }
252 
253 template <typename DATA>
254 inline void
256  std::vector<DATA const*>& data) const
257 {
258  data.assign(size, 0);
259 }
260 
261 template <typename DATA>
262 template <typename ASSNS>
263 inline void
265  ASSNS const& assns,
266  size_t data_index,
267  std::vector<DATA const*>& data) const
268 {
269  data[data_index] = &assns.data(assns_index);
270 }
271 
272 template <typename DATA>
273 inline void
275  size_t size,
276  std::vector<std::vector<DATA const*>>& data) const
277 {
278  data.resize(size);
279 }
280 
281 template <typename DATA>
282 template <typename ASSNS>
283 inline void
285  ptrdiff_t assns_index,
286  ASSNS const& assns,
287  size_t data_index,
288  std::vector<std::vector<DATA const*>>& data) const
289 {
290  data[data_index].push_back(&assns.data(assns_index));
291 }
292 
293 template <typename DATA>
294 inline void
296 {}
297 
298 template <typename DATA>
299 template <typename ASSNS>
300 inline void
302  ASSNS const&,
303  size_t,
304  IPRHelperDef&) const
305 {}
306 
307 template <typename ProdB>
309  : assnsTag_(assnsTag), seen_()
310 {}
311 
312 template <typename ProdB>
313 template <typename Bcoll>
314 inline void
315 art::detail::BcollHelper<ProdB>::init(size_t size, Bcoll& bColl)
316 {
317  // This works if BColl is a collection of pointers or Ptrs.
318  bColl.assign(size, typename Bcoll::value_type());
319  seen_.assign(size, uint8_t(0u));
320 }
321 
322 // 1.
323 template <typename ProdB>
324 template <typename Bcoll>
325 inline std::enable_if_t<
328  Ptr<ProdB> const& item,
329  Bcoll& bColl)
330 {
331  // This works if BColl is a collection of pointers or Ptrs.
332  if (seen_[index] == uint8_t(1u)) {
334  << "Attempted to create a FindOne object for a one-many or many-many"
335  << " association specified in collection " << assnsTag_ << ".\n";
336  } else if (item) {
337  bColl[index] = item.get();
338  seen_[index] = uint8_t(1u);
339  } else {
341  << "Attempted to create a FindOne object where an associated item is "
342  << "\nunavailable.\n";
343  }
344 }
345 
346 // 2.
347 template <typename ProdB>
348 template <typename Bcoll>
349 inline std::enable_if_t<
350  std::is_convertible<typename Bcoll::value_type, art::Ptr<ProdB>>::value>
352  Ptr<ProdB> const& item,
353  Bcoll& bColl)
354 {
355  // This works if BColl is a collection of pointers or Ptrs.
356  if (seen_[index] == uint8_t(1u)) {
358  << "Attempted to create a FindOne object for a one-many or many-many"
359  << " association specified in collection " << assnsTag_ << ".\n";
360  }
361  bColl[index] = item;
362  seen_[index] = uint8_t(1u);
363 }
364 
365 template <typename ProdB>
366 template <typename Bcoll>
367 inline void
369  std::vector<Bcoll>& bColls) const
370 {
371  bColls.resize(size);
372 }
373 
374 // 3.
375 template <typename ProdB>
376 template <typename Bcoll>
377 inline std::enable_if_t<
380  Ptr<ProdB> const& item,
381  std::vector<Bcoll>& bColls) const
382 {
383  bColls[index].push_back(item ? item.get() : nullptr);
384 }
385 
386 // 4.
387 template <typename ProdB>
388 template <typename Bcoll>
389 inline std::enable_if_t<
390  std::is_convertible<typename Bcoll::value_type, art::Ptr<ProdB>>::value>
392  Ptr<ProdB> const& item,
393  std::vector<Bcoll>& bColls) const
394 {
395  bColls[index].push_back(item);
396 }
397 
398 #endif /* canvas_Persistency_Common_detail_IPRHelper_h */
399 
400 // Local Variables:
401 // mode: c++
402 // End:
InputTag input_tag(InputTag const &tag)
Definition: IPRHelper.h:21
BcollHelper(InputTag const &assnsTag)
Definition: IPRHelper.h:308
void init(size_t size, std::vector< DATA const * > &data) const
Definition: IPRHelper.h:255
std::conditional_t< std::is_void< Data >::value, IPRHelperDef, DATACOLL > dataColl_t
Definition: IPRHelper.h:129
void init(size_t size, Bcoll &bColl)
Definition: IPRHelper.h:315
void fill(ptrdiff_t assns_index, ASSNS const &assns, size_t data_index, std::vector< DATA const * > &data) const
Definition: IPRHelper.h:264
InputTag const assnsTag_
Definition: IPRHelper.h:154
std::enable_if_t< std::is_same< typename Bcoll::value_type, ProdB const * >::value > fill(size_t index, Ptr< ProdB > const &item, Bcoll &bColl)
Definition: IPRHelper.h:327
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
EVENT const & event_
Definition: IPRHelper.h:153
shared_exception_t operator()(Acoll const &aColl, Bcoll &bColl) const
intermediate_table::const_iterator const_iterator
std::vector< uint8_t > seen_
Definition: IPRHelper.h:115
InputTag inputTag_
Definition: ProductToken.h:87
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
InputTag const assnsTag_
Definition: IPRHelper.h:114
InputTag inputTag_
Definition: ProductToken.h:65
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string value(boost::any const &)
T const * get() const
Definition: Ptr.h:321
std::shared_ptr< art::Exception const > shared_exception_t
Definition: IPRHelper.h:132
HLT enums.
Float_t e
Definition: plot.C:34
Definition: fwd.h:25
WANTED_POINTER ensurePointer(InputIterator it)
Definition: ensurePointer.h:77
T const * const_pointer
Definition: Ptr.h:104
IPRHelper(EVENT const &e, InputTag const &tag)
Definition: IPRHelper.h:134