LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
PropertySet.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more errors.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
26 
27 #include <algorithm>
28 #include <iomanip>
29 #include <sstream>
30 #include <stdexcept>
31 
33 #include "lsst/daf/base/DateTime.h"
34 
35 namespace lsst {
36 namespace daf {
37 namespace base {
38 
39 namespace {
40 
47 template <typename T>
48 void _append(std::vector<boost::any>& dest, std::vector<T> const& src) {
49  dest.reserve(dest.size() + src.size());
50  for (const T& val : src) {
51  dest.push_back(static_cast<T>(val));
52  }
53 }
54 
55 } // namespace
56 
57 PropertySet::PropertySet(bool flat) : _flat(flat) {}
58 
59 PropertySet::~PropertySet() noexcept = default;
60 
62 // Accessors
64 
65 PropertySet::Ptr PropertySet::deepCopy() const {
66  Ptr n(new PropertySet(_flat));
67  for (auto const& elt : _map) {
68  if (elt.second->back().type() == typeid(Ptr)) {
69  for (auto const& j : *elt.second) {
70  Ptr p = boost::any_cast<Ptr>(j);
71  if (p.get() == 0) {
72  n->add(elt.first, Ptr());
73  } else {
74  n->add(elt.first, p->deepCopy());
75  }
76  }
77  } else {
79  n->_map[elt.first] = vp;
80  }
81  }
82  return n;
83 }
84 
85 size_t PropertySet::nameCount(bool topLevelOnly) const {
86  int n = 0;
87  for (auto const& elt : _map) {
88  ++n;
89  if (!topLevelOnly && elt.second->back().type() == typeid(Ptr)) {
90  Ptr p = boost::any_cast<Ptr>(elt.second->back());
91  if (p.get() != 0) {
92  n += p->nameCount(false);
93  }
94  }
95  }
96  return n;
97 }
98 
99 std::vector<std::string> PropertySet::names(bool topLevelOnly) const {
101  for (auto const& elt : _map) {
102  v.push_back(elt.first);
103  if (!topLevelOnly && elt.second->back().type() == typeid(Ptr)) {
104  Ptr p = boost::any_cast<Ptr>(elt.second->back());
105  if (p.get() != 0) {
106  std::vector<std::string> w = p->names(false);
107  for (auto const& k : w) {
108  v.push_back(elt.first + "." + k);
109  }
110  }
111  }
112  }
113  return v;
114 }
115 
116 std::vector<std::string> PropertySet::paramNames(bool topLevelOnly) const {
118  for (auto const& elt : _map) {
119  if (elt.second->back().type() == typeid(Ptr)) {
120  Ptr p = boost::any_cast<Ptr>(elt.second->back());
121  if (p.get() != 0 && !topLevelOnly) {
122  std::vector<std::string> w = p->paramNames(false);
123  for (auto const& k : w) {
124  v.push_back(elt.first + "." + k);
125  }
126  }
127  } else {
128  v.push_back(elt.first);
129  }
130  }
131  return v;
132 }
133 
136  for (auto const& elt : _map) {
137  if (elt.second->back().type() == typeid(Ptr)) {
138  v.push_back(elt.first);
139  Ptr p = boost::any_cast<Ptr>(elt.second->back());
140  if (p.get() != 0 && !topLevelOnly) {
141  std::vector<std::string> w = p->propertySetNames(false);
142  for (auto const& k : w) {
143  v.push_back(elt.first + "." + k);
144  }
145  }
146  }
147  }
148  return v;
149 }
150 
151 bool PropertySet::exists(std::string const& name) const { return _find(name) != _map.end(); }
152 
153 bool PropertySet::isArray(std::string const& name) const {
154  auto const i = _find(name);
155  return i != _map.end() && i->second->size() > 1U;
156 }
157 
158 bool PropertySet::isPropertySetPtr(std::string const& name) const {
159  auto const i = _find(name);
160  return i != _map.end() && i->second->back().type() == typeid(Ptr);
161 }
162 
163 bool PropertySet::isUndefined(std::string const& name) const {
164  auto const i = _find(name);
165  return i != _map.end() && i->second->back().type() == typeid(nullptr);
166 }
167 
168 size_t PropertySet::valueCount(std::string const& name) const {
169  auto const i = _find(name);
170  if (i == _map.end()) return 0;
171  return i->second->size();
172 }
173 
174 std::type_info const& PropertySet::typeOf(std::string const& name) const {
175  auto const i = _find(name);
176  if (i == _map.end()) {
177  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
178  }
179  return i->second->back().type();
180 }
181 
182 template <typename T>
184  return typeid(T);
185 }
186 
187 // The following throw an exception if the type does not match exactly.
188 
189 template <typename T>
190 T PropertySet::get(std::string const& name)
191  const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
192  auto const i = _find(name);
193  if (i == _map.end()) {
194  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
195  }
196  try {
197  return boost::any_cast<T>(i->second->back());
198  } catch (boost::bad_any_cast) {
199  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
200  }
201  // not reached
202  return boost::any_cast<T>(i->second->back());
203 }
204 
205 template <typename T>
206 T PropertySet::get(std::string const& name, T const& defaultValue)
207  const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
208  auto const i = _find(name);
209  if (i == _map.end()) {
210  return defaultValue;
211  }
212  try {
213  return boost::any_cast<T>(i->second->back());
214  } catch (boost::bad_any_cast) {
215  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
216  }
217  // not reached
218  return boost::any_cast<T>(i->second->back());
219 }
220 
221 template <typename T>
223  auto const i = _find(name);
224  if (i == _map.end()) {
225  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
226  }
227  std::vector<T> v;
228  for (auto const& j : *(i->second)) {
229  try {
230  v.push_back(boost::any_cast<T>(j));
231  } catch (boost::bad_any_cast) {
232  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
233  }
234  }
235  return v;
236 }
237 
238 // The following throw an exception if the conversion is inappropriate.
239 
240 bool PropertySet::getAsBool(std::string const& name)
241  const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "for symmetry with other types" */
242  return get<bool>(name);
243 }
244 
245 int PropertySet::getAsInt(std::string const& name) const {
246  auto const i = _find(name);
247  if (i == _map.end()) {
248  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
249  }
250  boost::any v = i->second->back();
251  std::type_info const& t = v.type();
252  if (t == typeid(bool)) {
253  return boost::any_cast<bool>(v);
254  } else if (t == typeid(char)) {
255  return boost::any_cast<char>(v);
256  } else if (t == typeid(signed char)) {
257  return boost::any_cast<signed char>(v);
258  } else if (t == typeid(unsigned char)) {
259  return boost::any_cast<unsigned char>(v);
260  } else if (t == typeid(short)) {
261  return boost::any_cast<short>(v);
262  } else if (t == typeid(unsigned short)) {
263  return boost::any_cast<unsigned short>(v);
264  }
265  try {
266  return boost::any_cast<int>(v);
267  } catch (boost::bad_any_cast) {
268  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
269  }
270  // not reached
271  return boost::any_cast<int>(v);
272 }
273 
274 int64_t PropertySet::getAsInt64(std::string const& name) const {
275  auto const i = _find(name);
276  if (i == _map.end()) {
277  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
278  }
279  boost::any v = i->second->back();
280  std::type_info const& t = v.type();
281  if (t == typeid(bool)) return boost::any_cast<bool>(v);
282  if (t == typeid(char)) return boost::any_cast<char>(v);
283  if (t == typeid(signed char)) return boost::any_cast<signed char>(v);
284  if (t == typeid(unsigned char)) return boost::any_cast<unsigned char>(v);
285  if (t == typeid(short)) return boost::any_cast<short>(v);
286  if (t == typeid(unsigned short)) return boost::any_cast<unsigned short>(v);
287  if (t == typeid(int)) return boost::any_cast<int>(v);
288  if (t == typeid(unsigned int)) return boost::any_cast<unsigned int>(v);
289  if (t == typeid(long)) return boost::any_cast<long>(v);
290  if (t == typeid(long long)) return boost::any_cast<long long>(v);
291  try {
292  return boost::any_cast<int64_t>(v);
293  } catch (boost::bad_any_cast) {
294  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
295  }
296  // not reached
297  return boost::any_cast<int64_t>(v);
298 }
299 
300 uint64_t PropertySet::getAsUInt64(std::string const& name) const {
301  auto const i = _find(name);
302  if (i == _map.end()) {
303  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
304  }
305  boost::any v = i->second->back();
306  std::type_info const& t = v.type();
307  if (t == typeid(bool)) return boost::any_cast<bool>(v);
308  if (t == typeid(char)) return boost::any_cast<char>(v);
309  if (t == typeid(signed char)) return boost::any_cast<signed char>(v);
310  if (t == typeid(unsigned char)) return boost::any_cast<unsigned char>(v);
311  if (t == typeid(short)) return boost::any_cast<short>(v);
312  if (t == typeid(unsigned short)) return boost::any_cast<unsigned short>(v);
313  if (t == typeid(int)) return boost::any_cast<int>(v);
314  if (t == typeid(unsigned int)) return boost::any_cast<unsigned int>(v);
315  if (t == typeid(long)) return boost::any_cast<long>(v);
316  if (t == typeid(long long)) return boost::any_cast<long long>(v);
317  if (t == typeid(unsigned long long)) return boost::any_cast<unsigned long long>(v);
318  try {
319  return boost::any_cast<uint64_t>(v);
320  } catch (boost::bad_any_cast) {
321  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
322  }
323  // not reached
324  return boost::any_cast<uint64_t>(v);
325 }
326 
327 double PropertySet::getAsDouble(std::string const& name) const {
328  auto const i = _find(name);
329  if (i == _map.end()) {
330  throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
331  }
332  boost::any v = i->second->back();
333  std::type_info const& t = v.type();
334  if (t == typeid(bool)) return boost::any_cast<bool>(v);
335  if (t == typeid(char)) return boost::any_cast<char>(v);
336  if (t == typeid(signed char)) return boost::any_cast<signed char>(v);
337  if (t == typeid(unsigned char)) return boost::any_cast<unsigned char>(v);
338  if (t == typeid(short)) return boost::any_cast<short>(v);
339  if (t == typeid(unsigned short)) return boost::any_cast<unsigned short>(v);
340  if (t == typeid(int)) return boost::any_cast<int>(v);
341  if (t == typeid(unsigned int)) return boost::any_cast<unsigned int>(v);
342  if (t == typeid(long)) return boost::any_cast<long>(v);
343  if (t == typeid(unsigned long)) return boost::any_cast<unsigned long>(v);
344  if (t == typeid(long long)) return boost::any_cast<long long>(v);
345  if (t == typeid(unsigned long long)) return boost::any_cast<unsigned long long>(v);
346  if (t == typeid(float)) return boost::any_cast<float>(v);
347  try {
348  return boost::any_cast<double>(v);
349  } catch (boost::bad_any_cast) {
350  throw LSST_EXCEPT(pex::exceptions::TypeError, name);
351  }
352  // not reached
353  return boost::any_cast<double>(v);
354 }
355 
356 std::string PropertySet::getAsString(std::string const& name) const { return get<std::string>(name); }
357 
358 PropertySet::Ptr PropertySet::getAsPropertySetPtr(std::string const& name) const { return get<Ptr>(name); }
359 
361  return get<Persistable::Ptr>(name);
362 }
363 
364 std::string PropertySet::toString(bool topLevelOnly, std::string const& indent) const {
367  sort(nv.begin(), nv.end());
368  for (auto const& i : nv) {
369  std::shared_ptr<std::vector<boost::any>> vp = _map.find(i)->second;
370  std::type_info const& t = vp->back().type();
371  if (t == typeid(Ptr)) {
372  s << indent << i << " = ";
373  if (topLevelOnly) {
374  s << "{ ... }";
375  } else {
376  Ptr p = boost::any_cast<Ptr>(vp->back());
377  if (p.get() == 0) {
378  s << "{ NULL }";
379  } else {
380  s << '{' << std::endl;
381  s << p->toString(false, indent + "..");
382  s << indent << '}';
383  }
384  }
385  s << std::endl;
386  } else {
387  s << indent << _format(i);
388  }
389  }
390  return s.str();
391 }
392 
393 std::string PropertySet::_format(std::string const& name) const {
395  s << std::showpoint; // Always show a decimal point for floats
396  auto const j = _map.find(name);
397  s << j->first << " = ";
399  if (vp->size() > 1) {
400  s << "[ ";
401  }
402  std::type_info const& t = vp->back().type();
403  bool isFirst = true;
404  for (auto const& k : *vp) {
405  if (isFirst) {
406  isFirst = false;
407  } else {
408  s << ", ";
409  }
410  boost::any const& v(k);
411  if (t == typeid(bool)) {
412  s << boost::any_cast<bool>(v);
413  } else if (t == typeid(char)) {
414  s << '\'' << boost::any_cast<char>(v) << '\'';
415  } else if (t == typeid(signed char)) {
416  s << '\'' << boost::any_cast<signed char>(v) << '\'';
417  } else if (t == typeid(unsigned char)) {
418  s << '\'' << boost::any_cast<unsigned char>(v) << '\'';
419  } else if (t == typeid(short)) {
420  s << boost::any_cast<short>(v);
421  } else if (t == typeid(unsigned short)) {
422  s << boost::any_cast<unsigned short>(v);
423  } else if (t == typeid(int)) {
424  s << boost::any_cast<int>(v);
425  } else if (t == typeid(unsigned int)) {
426  s << boost::any_cast<unsigned int>(v);
427  } else if (t == typeid(long)) {
428  s << boost::any_cast<long>(v);
429  } else if (t == typeid(unsigned long)) {
430  s << boost::any_cast<unsigned long>(v);
431  } else if (t == typeid(long long)) {
432  s << boost::any_cast<long long>(v);
433  } else if (t == typeid(unsigned long long)) {
434  s << boost::any_cast<unsigned long long>(v);
435  } else if (t == typeid(float)) {
436  s << std::setprecision(7) << boost::any_cast<float>(v);
437  } else if (t == typeid(double)) {
438  s << std::setprecision(14) << boost::any_cast<double>(v);
439  } else if (t == typeid(std::string)) {
440  s << '"' << boost::any_cast<std::string>(v) << '"';
441  } else if (t == typeid(DateTime)) {
442  s << boost::any_cast<DateTime>(v).toString(DateTime::UTC);
443  } else if (t == typeid(Ptr)) {
444  s << "{ ... }";
445  } else if (t == typeid(Persistable::Ptr)) {
446  s << "<Persistable>";
447  } else {
448  s << "<Unknown>";
449  }
450  }
451  if (j->second->size() > 1) {
452  s << " ]";
453  }
454  s << std::endl;
455  return s.str();
456 }
457 
459 // Modifiers
461 
462 template <typename T>
463 void PropertySet::set(std::string const& name, T const& value) {
465  vp->push_back(value);
466  _set(name, vp);
467 }
468 
469 template <typename T>
470 void PropertySet::set(std::string const& name, std::vector<T> const& value) {
471  if (value.empty()) return;
473  _append(*vp, value);
474  _set(name, vp);
475 }
476 
477 void PropertySet::set(std::string const& name, char const* value) { set(name, std::string(value)); }
478 
479 template <typename T>
480 void PropertySet::add(std::string const& name, T const& value) {
481  AnyMap::iterator i = _find(name);
482  if (i == _map.end()) {
483  set(name, value);
484  } else {
485  if (i->second->back().type() != typeid(T)) {
486  throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
487  }
488  i->second->push_back(value);
489  }
490 }
491 
492 // Specialize for Ptrs to check for cycles.
493 template <>
494 void PropertySet::add<PropertySet::Ptr>(std::string const& name, Ptr const& value) {
495  AnyMap::iterator i = _find(name);
496  if (i == _map.end()) {
497  set(name, value);
498  } else {
499  if (i->second->back().type() != typeid(Ptr)) {
500  throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
501  }
502  _cycleCheckPtr(value, name);
503  i->second->push_back(value);
504  }
505 }
506 
507 template <typename T>
508 void PropertySet::add(std::string const& name, std::vector<T> const& value) {
509  AnyMap::iterator i = _find(name);
510  if (i == _map.end()) {
511  set(name, value);
512  } else {
513  if (i->second->back().type() != typeid(T)) {
514  throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
515  }
516  _append(*(i->second), value);
517  }
518 }
519 
520 // Specialize for Ptrs to check for cycles.
521 template <>
522 void PropertySet::add<PropertySet::Ptr>(std::string const& name, std::vector<Ptr> const& value) {
523  AnyMap::iterator i = _find(name);
524  if (i == _map.end()) {
525  set(name, value);
526  } else {
527  if (i->second->back().type() != typeid(Ptr)) {
528  throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
529  }
530  _cycleCheckPtrVec(value, name);
531  _append(*(i->second), value);
532  }
533 }
534 
535 void PropertySet::add(std::string const& name, char const* value) { add(name, std::string(value)); }
536 
537 void PropertySet::copy(std::string const& dest, ConstPtr source, std::string const& name, bool asScalar) {
538  if (source.get() == 0) {
539  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, "Missing source");
540  }
541  auto const sj = source->_find(name);
542  if (sj == source->_map.end()) {
543  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " not in source");
544  }
545  remove(dest);
546  if (asScalar) {
547  auto vp = std::make_shared<std::vector<boost::any>>();
548  vp->push_back(sj->second->back());
549  _set(dest, vp);
550  } else {
551  auto vp = std::make_shared<std::vector<boost::any>>(*(sj->second));
552  _set(dest, vp);
553  }
554 }
555 
556 void PropertySet::combine(ConstPtr source) {
557  if (source.get() == 0) {
558  return;
559  }
560  std::vector<std::string> names = source->paramNames(false);
561  for (auto const& name : names) {
562  auto const sp = source->_find(name);
563  _add(name, sp->second);
564  }
565 }
566 
567 void PropertySet::remove(std::string const& name) {
568  std::string::size_type i = name.find('.');
569  if (_flat || i == name.npos) {
570  _map.erase(name);
571  return;
572  }
573  std::string prefix(name, 0, i);
574  AnyMap::iterator j = _map.find(prefix);
575  if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
576  return;
577  }
578  Ptr p = boost::any_cast<Ptr>(j->second->back());
579  if (p.get() != 0) {
580  std::string suffix(name, i + 1);
581  p->remove(suffix);
582  }
583 }
584 
586 // Private member functions
588 
589 PropertySet::AnyMap::iterator PropertySet::_find(std::string const& name) {
590  std::string::size_type i = name.find('.');
591  if (_flat || i == name.npos) {
592  return _map.find(name);
593  }
594  std::string prefix(name, 0, i);
595  AnyMap::iterator j = _map.find(prefix);
596  if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
597  return _map.end();
598  }
599  Ptr p = boost::any_cast<Ptr>(j->second->back());
600  if (p.get() == 0) {
601  return _map.end();
602  }
603  std::string suffix(name, i + 1);
604  AnyMap::iterator x = p->_find(suffix);
605  if (x == p->_map.end()) {
606  return _map.end();
607  }
608  return x;
609 }
610 
611 PropertySet::AnyMap::const_iterator PropertySet::_find(std::string const& name) const {
612  std::string::size_type i = name.find('.');
613  if (_flat || i == name.npos) {
614  return _map.find(name);
615  }
616  std::string prefix(name, 0, i);
617  auto const j = _map.find(prefix);
618  if (j == _map.end() || j->second->back().type() != typeid(Ptr)) {
619  return _map.end();
620  }
621  Ptr p = boost::any_cast<Ptr>(j->second->back());
622  if (p.get() == 0) {
623  return _map.end();
624  }
625  std::string suffix(name, i + 1);
626  auto const x = p->_find(suffix);
627  if (x == p->_map.end()) {
628  return _map.end();
629  }
630  return x;
631 }
632 
634  _findOrInsert(name, vp);
635 }
636 
638  auto const dp = _find(name);
639  if (dp == _map.end()) {
640  _set(name, vp);
641  } else {
642  if (vp->back().type() != dp->second->back().type()) {
643  throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
644  }
645  // Check for cycles
646  if (vp->back().type() == typeid(Ptr)) {
647  _cycleCheckAnyVec(*vp, name);
648  }
649  _append(*(dp->second), *vp);
650  }
651 }
652 
653 void PropertySet::_findOrInsert(std::string const& name, std::shared_ptr<std::vector<boost::any>> vp) {
654  if (vp->back().type() == typeid(Ptr)) {
655  if (_flat) {
656  Ptr source = boost::any_cast<Ptr>(vp->back());
657  std::vector<std::string> names = source->paramNames(false);
658  for (auto const& i : names) {
659  auto const sp = source->_find(i);
660  _add(name + "." + i, sp->second);
661  }
662  return;
663  }
664 
665  // Check for cycles
666  _cycleCheckAnyVec(*vp, name);
667  }
668 
669  std::string::size_type i = name.find('.');
670  if (_flat || i == name.npos) {
671  _map[name] = vp;
672  return;
673  }
674  std::string prefix(name, 0, i);
675  std::string suffix(name, i + 1);
676  AnyMap::iterator j = _map.find(prefix);
677  if (j == _map.end()) {
679  pp->_findOrInsert(suffix, vp);
681  temp->push_back(pp);
682  _map[prefix] = temp;
683  return;
684  } else if (j->second->back().type() != typeid(Ptr)) {
685  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
686  prefix + " exists but does not contain PropertySet::Ptrs");
687  }
688  Ptr p = boost::any_cast<Ptr>(j->second->back());
689  if (p.get() == 0) {
690  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
691  prefix + " exists but contains null PropertySet::Ptr");
692  }
693  p->_findOrInsert(suffix, vp);
694 }
695 
696 void PropertySet::_cycleCheckPtrVec(std::vector<Ptr> const& v, std::string const& name) {
697  for (auto const& i : v) {
698  _cycleCheckPtr(i, name);
699  }
700 }
701 
702 void PropertySet::_cycleCheckAnyVec(std::vector<boost::any> const& v, std::string const& name) {
703  for (auto const& i : v) {
704  _cycleCheckPtr(boost::any_cast<Ptr>(i), name);
705  }
706 }
707 
708 void PropertySet::_cycleCheckPtr(Ptr const& v, std::string const& name) {
709  if (v.get() == this) {
710  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
711  }
712  std::vector<std::string> sets = v->propertySetNames(false);
713  for (auto const& i : sets) {
714  if (v->getAsPropertySetPtr(i).get() == this) {
715  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
716  }
717  }
718 }
719 
721  // Explicit template instantiations
723 
725  // Explicit template instantiations are not well understood by doxygen.
726 
727 #define INSTANTIATE(t) \
728  template std::type_info const& PropertySet::typeOfT<t>(); \
729  template t PropertySet::get<t>(std::string const& name) const; \
730  template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
731  template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
732  template void PropertySet::set<t>(std::string const& name, t const& value); \
733  template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value); \
734  template void PropertySet::add<t>(std::string const& name, t const& value); \
735  template void PropertySet::add<t>(std::string const& name, std::vector<t> const& value);
736 
737 #define INSTANTIATE_PROPERTY_SET(t) \
738  template std::type_info const& PropertySet::typeOfT<t>(); \
739  template t PropertySet::get<t>(std::string const& name) const; \
740  template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
741  template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
742  template void PropertySet::set<t>(std::string const& name, t const& value); \
743  template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value);
744 
745 INSTANTIATE(bool)
746 INSTANTIATE(char)
747 INSTANTIATE(signed char)
748 INSTANTIATE(unsigned char)
749 INSTANTIATE(short)
750 INSTANTIATE(unsigned short)
751 INSTANTIATE(int)
752 INSTANTIATE(unsigned int)
753 INSTANTIATE(long)
754 INSTANTIATE(unsigned long)
755 INSTANTIATE(long long)
756 INSTANTIATE(unsigned long long)
757 INSTANTIATE(float)
758 INSTANTIATE(double)
761 INSTANTIATE_PROPERTY_SET(PropertySet::Ptr)
763 INSTANTIATE(DateTime)
764 
765 } // namespace base
766 } // namespace daf
767 } // namespace lsst
768 
double getAsDouble(std::string const &name) const
Get the last value for any arithmetic property name (possibly hierarchical).
virtual std::string toString(bool topLevelOnly=false, std::string const &indent="") const
Generate a string representation of the PropertySet.
static std::type_info const & typeOfT()
Get type info for the specified class.
T empty(T... args)
std::shared_ptr< PropertySet > Ptr
Definition: PropertySet.h:70
virtual void copy(std::string const &dest, ConstPtr source, std::string const &name, bool asScalar=false)
Replace a single value vector in the destination with one from the source.
size_t valueCount(std::string const &name) const
Get the number of values for a property name (possibly hierarchical).
std::vector< T > getArray(std::string const &name) const
Get the vector of values for a property name (possibly hierarchical).
virtual void combine(ConstPtr source)
Append all value vectors from the source to their corresponding properties.
T get(std::string const &name) const
Get the last value for a property name (possibly hierarchical).
bool getAsBool(std::string const &name) const
Get the last value for a bool property name (possibly hierarchical).
std::vector< std::string > propertySetNames(bool topLevelOnly=true) const
A variant of names that only returns the names of subproperties.
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
T endl(T... args)
ImageT val
Definition: CR.cc:146
PropertySet::Ptr getAsPropertySetPtr(std::string const &name) const
Get the last value for a subproperty name (possibly hierarchical).
std::shared_ptr< PropertySet const > ConstPtr
Definition: PropertySet.h:71
virtual std::string _format(std::string const &name) const
T end(T... args)
bool isPropertySetPtr(std::string const &name) const
Determine if a name (possibly hierarchical) is a subproperty.
virtual void remove(std::string const &name)
Remove all values for a property name (possibly hierarchical).
std::vector< std::string > paramNames(bool topLevelOnly=true) const
A variant of names that excludes the names of subproperties.
PropertySet(bool flat=false)
Construct an empty PropertySet.
void set(std::string const &name, T const &value)
Replace all values for a property name (possibly hierarchical) with a new scalar value.
uint64_t getAsUInt64(std::string const &name) const
Get the last value for an bool/char/short/int/int64_t property name (possibly hierarchical).
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.
STL class.
bool isArray(std::string const &name) const
Determine if a name (possibly hierarchical) has multiple values.
T push_back(T... args)
A base class for image defects.
int64_t getAsInt64(std::string const &name) const
Get the last value for a bool/char/short/int/int64_t property name (possibly hierarchical).
std::shared_ptr< RecordT > src
Definition: Match.cc:48
size_t nameCount(bool topLevelOnly=true) const
Get the number of names in the PropertySet, optionally including those in subproperties.
T str(T... args)
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
T showpoint(T... args)
const char * source()
Source function that allows astChannel to source from a Stream.
Definition: Stream.h:224
virtual void _set(std::string const &name, std::shared_ptr< std::vector< boost::any > > vp)
double x
Interface for DateTime class.
Persistable::Ptr getAsPersistablePtr(std::string const &name) const
Get the last value for a Persistable name (possibly hierarchical).
double w
Definition: CoaddPsf.cc:69
T find(T... args)
Definition: __init__.py:1
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
STL class.
virtual void _add(std::string const &name, std::shared_ptr< std::vector< boost::any > > vp)
T begin(T... args)
T back(T... args)
std::string prefix
Definition: SchemaMapper.cc:79
virtual ~PropertySet() noexcept
Destructor.
std::shared_ptr< Persistable > Ptr
Definition: Persistable.h:77
T sort(T... args)
std::string getAsString(std::string const &name) const
Get the last value for a string property name (possibly hierarchical).
std::vector< std::string > names(bool topLevelOnly=true) const
Get the names in the PropertySet, optionally including those in subproperties.
void add(std::string const &name, T const &value)
Append a single value to the vector of values for a property name (possibly hierarchical).
bool isUndefined(std::string const &name) const
Determine if a name (possibly hierarchical) has a defined value.
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
T reserve(T... args)
std::type_info const & typeOf(std::string const &name) const
Get the type of values for a property name (possibly hierarchical).