LSST Applications g0603fd7c41+501e3db9f9,g0aad566f14+23d8574c86,g0dd44d6229+a1a4c8b791,g2079a07aa2+86d27d4dc4,g2305ad1205+a62672bbc1,g2bbee38e9b+047b288a59,g337abbeb29+047b288a59,g33d1c0ed96+047b288a59,g3a166c0a6a+047b288a59,g3d1719c13e+23d8574c86,g487adcacf7+cb7fd919b2,g4be5004598+23d8574c86,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+4a9e435310,g63cd9335cc+585e252eca,g858d7b2824+23d8574c86,g88963caddf+0cb8e002cc,g99cad8db69+43388bcaec,g9ddcbc5298+9a081db1e4,ga1e77700b3+a912195c07,gae0086650b+585e252eca,gb0e22166c9+60f28cb32d,gb2522980b2+793639e996,gb3a676b8dc+b4feba26a1,gb4b16eec92+63f8520565,gba4ed39666+c2a2e4ac27,gbb8dafda3b+a5d255a82e,gc120e1dc64+d820f8acdb,gc28159a63d+047b288a59,gc3e9b769f7+f4f1cc6b50,gcf0d15dbbd+a1a4c8b791,gdaeeff99f8+f9a426f77a,gdb0af172c8+b6d5496702,ge79ae78c31+047b288a59,w.2024.19
LSST Data Management Base Package
Loading...
Searching...
No Matches
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#include <any>
32
35
36namespace lsst {
37namespace daf {
38namespace base {
39
40namespace {
41
48template <typename T>
49void _append(std::vector<std::any>& dest, std::vector<T> const& src) {
50 dest.reserve(dest.size() + src.size());
51 for (const T& val : src) {
52 dest.push_back(static_cast<T>(val));
53 }
54}
55
56} // namespace
57
58PropertySet::PropertySet(bool flat) : _flat(flat) {}
59
60PropertySet::~PropertySet() noexcept = default;
61
63// Accessors
65
66std::shared_ptr<PropertySet> PropertySet::deepCopy() const {
67 auto n = std::make_shared<PropertySet>(_flat);
68 for (auto const& elt : _map) {
69 if (elt.second->back().type() == typeid(std::shared_ptr<PropertySet>)) {
70 for (auto const& j : *elt.second) {
71 auto p = std::any_cast<std::shared_ptr<PropertySet>>(j);
72 if (p.get() == 0) {
73 n->add(elt.first, std::shared_ptr<PropertySet>());
74 } else {
75 n->add(elt.first, p->deepCopy());
76 }
77 }
78 } else {
80 n->_map[elt.first] = vp;
81 }
82 }
83 return n;
84}
85
86size_t PropertySet::nameCount(bool topLevelOnly) const {
87 int n = 0;
88 for (auto const& elt : _map) {
89 ++n;
90 if (!topLevelOnly && elt.second->back().type() == typeid(std::shared_ptr<PropertySet>)) {
91 auto p = std::any_cast<std::shared_ptr<PropertySet>>(elt.second->back());
92 if (p.get() != 0) {
93 n += p->nameCount(false);
94 }
95 }
96 }
97 return n;
98}
99
100std::vector<std::string> PropertySet::names(bool topLevelOnly) const {
102 for (auto const& elt : _map) {
103 v.push_back(elt.first);
104 if (!topLevelOnly && elt.second->back().type() == typeid(std::shared_ptr<PropertySet>)) {
105 auto p = std::any_cast<std::shared_ptr<PropertySet>>(elt.second->back());
106 if (p.get() != 0) {
107 std::vector<std::string> w = p->names(false);
108 for (auto const& k : w) {
109 v.push_back(elt.first + "." + k);
110 }
111 }
112 }
113 }
114 return v;
115}
116
117std::vector<std::string> PropertySet::paramNames(bool topLevelOnly) const {
119 for (auto const& elt : _map) {
120 if (elt.second->back().type() == typeid(std::shared_ptr<PropertySet>)) {
121 auto p = std::any_cast<std::shared_ptr<PropertySet>>(elt.second->back());
122 if (p.get() != 0 && !topLevelOnly) {
123 std::vector<std::string> w = p->paramNames(false);
124 for (auto const& k : w) {
125 v.push_back(elt.first + "." + k);
126 }
127 }
128 } else {
129 v.push_back(elt.first);
130 }
131 }
132 return v;
133}
134
135std::vector<std::string> PropertySet::propertySetNames(bool topLevelOnly) const {
137 for (auto const& elt : _map) {
138 if (elt.second->back().type() == typeid(std::shared_ptr<PropertySet>)) {
139 v.push_back(elt.first);
140 auto p = std::any_cast<std::shared_ptr<PropertySet>>(elt.second->back());
141 if (p.get() != 0 && !topLevelOnly) {
142 std::vector<std::string> w = p->propertySetNames(false);
143 for (auto const& k : w) {
144 v.push_back(elt.first + "." + k);
145 }
146 }
147 }
148 }
149 return v;
150}
151
152bool PropertySet::exists(std::string const& name) const { return _find(name) != _map.end(); }
153
154bool PropertySet::isArray(std::string const& name) const {
155 auto const i = _find(name);
156 return i != _map.end() && i->second->size() > 1U;
157}
158
159bool PropertySet::isPropertySetPtr(std::string const& name) const {
160 auto const i = _find(name);
161 return i != _map.end() && i->second->back().type() == typeid(std::shared_ptr<PropertySet>);
162}
163
164bool PropertySet::isUndefined(std::string const& name) const {
165 auto const i = _find(name);
166 return i != _map.end() && i->second->back().type() == typeid(nullptr);
167}
168
169size_t PropertySet::valueCount() const {
170 size_t sum = 0;
171 for (auto const& name : paramNames(false)) {
172 sum += valueCount(name);
173 }
174 return sum;
175}
176
177size_t PropertySet::valueCount(std::string const& name) const {
178 auto const i = _find(name);
179 if (i == _map.end()) return 0;
180 return i->second->size();
181}
182
183std::type_info const& PropertySet::typeOf(std::string const& name) const {
184 auto const i = _find(name);
185 if (i == _map.end()) {
186 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
187 }
188 return i->second->back().type();
189}
190
191template <typename T>
192std::type_info const& PropertySet::typeOfT() {
193 return typeid(T);
194}
195
196// The following throw an exception if the type does not match exactly.
197
198template <typename T>
199T PropertySet::get(std::string const& name)
200 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
201 auto const i = _find(name);
202 if (i == _map.end()) {
203 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
204 }
205 try {
206 return std::any_cast<T>(i->second->back());
207 } catch (std::bad_any_cast &) {
208 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
209 }
210 // not reached
211 return std::any_cast<T>(i->second->back());
212}
213
214template <typename T>
215T PropertySet::get(std::string const& name, T const& defaultValue)
216 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "allow template over bool" */
217 auto const i = _find(name);
218 if (i == _map.end()) {
219 return defaultValue;
220 }
221 try {
222 return std::any_cast<T>(i->second->back());
223 } catch (std::bad_any_cast &) {
224 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
225 }
226 // not reached
227 return std::any_cast<T>(i->second->back());
228}
229
230template <typename T>
231std::vector<T> PropertySet::getArray(std::string const& name) const {
232 auto const i = _find(name);
233 if (i == _map.end()) {
234 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
235 }
237 for (auto const& j : *(i->second)) {
238 try {
239 v.push_back(std::any_cast<T>(j));
240 } catch (std::bad_any_cast &) {
241 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
242 }
243 }
244 return v;
245}
246
247// The following throw an exception if the conversion is inappropriate.
248
249bool PropertySet::getAsBool(std::string const& name)
250 const { /* parasoft-suppress LsstDm-3-4a LsstDm-4-6 "for symmetry with other types" */
251 return get<bool>(name);
252}
253
254int PropertySet::getAsInt(std::string const& name) const {
255 auto const i = _find(name);
256 if (i == _map.end()) {
257 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
258 }
259 std::any v = i->second->back();
260 std::type_info const& t = v.type();
261 if (t == typeid(bool)) {
262 return std::any_cast<bool>(v);
263 } else if (t == typeid(char)) {
264 return std::any_cast<char>(v);
265 } else if (t == typeid(signed char)) {
266 return std::any_cast<signed char>(v);
267 } else if (t == typeid(unsigned char)) {
268 return std::any_cast<unsigned char>(v);
269 } else if (t == typeid(short)) {
270 return std::any_cast<short>(v);
271 } else if (t == typeid(unsigned short)) {
272 return std::any_cast<unsigned short>(v);
273 }
274 try {
275 return std::any_cast<int>(v);
276 } catch (std::bad_any_cast &) {
277 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
278 }
279 // not reached
280 return std::any_cast<int>(v);
281}
282
283int64_t PropertySet::getAsInt64(std::string const& name) const {
284 auto const i = _find(name);
285 if (i == _map.end()) {
286 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
287 }
288 std::any v = i->second->back();
289 std::type_info const& t = v.type();
290 if (t == typeid(bool)) return std::any_cast<bool>(v);
291 if (t == typeid(char)) return std::any_cast<char>(v);
292 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
293 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
294 if (t == typeid(short)) return std::any_cast<short>(v);
295 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
296 if (t == typeid(int)) return std::any_cast<int>(v);
297 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
298 if (t == typeid(long)) return std::any_cast<long>(v);
299 if (t == typeid(long long)) return std::any_cast<long long>(v);
300 try {
301 return std::any_cast<int64_t>(v);
302 } catch (std::bad_any_cast &) {
303 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
304 }
305 // not reached
306 return std::any_cast<int64_t>(v);
307}
308
309uint64_t PropertySet::getAsUInt64(std::string const& name) const {
310 auto const i = _find(name);
311 if (i == _map.end()) {
312 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
313 }
314 std::any v = i->second->back();
315 std::type_info const& t = v.type();
316 if (t == typeid(bool)) return std::any_cast<bool>(v);
317 if (t == typeid(char)) return std::any_cast<char>(v);
318 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
319 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
320 if (t == typeid(short)) return std::any_cast<short>(v);
321 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
322 if (t == typeid(int)) return std::any_cast<int>(v);
323 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
324 if (t == typeid(long)) return std::any_cast<long>(v);
325 if (t == typeid(long long)) return std::any_cast<long long>(v);
326 if (t == typeid(unsigned long long)) return std::any_cast<unsigned long long>(v);
327 try {
328 return std::any_cast<uint64_t>(v);
329 } catch (std::bad_any_cast &) {
330 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
331 }
332 // not reached
333 return std::any_cast<uint64_t>(v);
334}
335
336double PropertySet::getAsDouble(std::string const& name) const {
337 auto const i = _find(name);
338 if (i == _map.end()) {
339 throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
340 }
341 std::any v = i->second->back();
342 std::type_info const& t = v.type();
343 if (t == typeid(bool)) return std::any_cast<bool>(v);
344 if (t == typeid(char)) return std::any_cast<char>(v);
345 if (t == typeid(signed char)) return std::any_cast<signed char>(v);
346 if (t == typeid(unsigned char)) return std::any_cast<unsigned char>(v);
347 if (t == typeid(short)) return std::any_cast<short>(v);
348 if (t == typeid(unsigned short)) return std::any_cast<unsigned short>(v);
349 if (t == typeid(int)) return std::any_cast<int>(v);
350 if (t == typeid(unsigned int)) return std::any_cast<unsigned int>(v);
351 if (t == typeid(long)) return std::any_cast<long>(v);
352 if (t == typeid(unsigned long)) return std::any_cast<unsigned long>(v);
353 if (t == typeid(long long)) return std::any_cast<long long>(v);
354 if (t == typeid(unsigned long long)) return std::any_cast<unsigned long long>(v);
355 if (t == typeid(float)) return std::any_cast<float>(v);
356 try {
357 return std::any_cast<double>(v);
358 } catch (std::bad_any_cast &) {
359 std::throw_with_nested(LSST_EXCEPT(pex::exceptions::TypeError, name));
360 }
361 // not reached
362 return std::any_cast<double>(v);
363}
364
365std::string PropertySet::getAsString(std::string const& name) const { return get<std::string>(name); }
366
367std::shared_ptr<PropertySet> PropertySet::getAsPropertySetPtr(std::string const& name) const {
368 return get<std::shared_ptr<PropertySet>>(name);
369}
370
371Persistable::Ptr PropertySet::getAsPersistablePtr(std::string const& name) const {
372 return get<Persistable::Ptr>(name);
373}
374
375std::string PropertySet::toString(bool topLevelOnly, std::string const& indent) const {
378 sort(nv.begin(), nv.end());
379 for (auto const& i : nv) {
380 std::shared_ptr<std::vector<std::any>> vp = _map.find(i)->second;
381 std::type_info const& t = vp->back().type();
382 if (t == typeid(std::shared_ptr<PropertySet>)) {
383 s << indent << i << " = ";
384 if (topLevelOnly) {
385 s << "{ ... }";
386 } else {
387 auto p = std::any_cast<std::shared_ptr<PropertySet>>(vp->back());
388 if (p.get() == 0) {
389 s << "{ NULL }";
390 } else {
391 s << '{' << std::endl;
392 s << p->toString(false, indent + "..");
393 s << indent << '}';
394 }
395 }
396 s << std::endl;
397 } else {
398 s << indent << _format(i);
399 }
400 }
401 return s.str();
402}
403
404std::string PropertySet::_format(std::string const& name) const {
406 s << std::showpoint; // Always show a decimal point for floats
407 auto const j = _map.find(name);
408 s << j->first << " = ";
410 if (vp->size() > 1) {
411 s << "[ ";
412 }
413 std::type_info const& t = vp->back().type();
414 bool isFirst = true;
415 for (auto const& k : *vp) {
416 if (isFirst) {
417 isFirst = false;
418 } else {
419 s << ", ";
420 }
421 std::any const& v(k);
422 if (t == typeid(bool)) {
423 s << std::any_cast<bool>(v);
424 } else if (t == typeid(char)) {
425 s << '\'' << std::any_cast<char>(v) << '\'';
426 } else if (t == typeid(signed char)) {
427 s << '\'' << std::any_cast<signed char>(v) << '\'';
428 } else if (t == typeid(unsigned char)) {
429 s << '\'' << std::any_cast<unsigned char>(v) << '\'';
430 } else if (t == typeid(short)) {
431 s << std::any_cast<short>(v);
432 } else if (t == typeid(unsigned short)) {
433 s << std::any_cast<unsigned short>(v);
434 } else if (t == typeid(int)) {
435 s << std::any_cast<int>(v);
436 } else if (t == typeid(unsigned int)) {
437 s << std::any_cast<unsigned int>(v);
438 } else if (t == typeid(long)) {
439 s << std::any_cast<long>(v);
440 } else if (t == typeid(unsigned long)) {
441 s << std::any_cast<unsigned long>(v);
442 } else if (t == typeid(long long)) {
443 s << std::any_cast<long long>(v);
444 } else if (t == typeid(unsigned long long)) {
445 s << std::any_cast<unsigned long long>(v);
446 } else if (t == typeid(float)) {
447 s << std::setprecision(7) << std::any_cast<float>(v);
448 } else if (t == typeid(double)) {
449 s << std::setprecision(14) << std::any_cast<double>(v);
450 } else if (t == typeid(std::string)) {
451 s << '"' << std::any_cast<std::string>(v) << '"';
452 } else if (t == typeid(DateTime)) {
453 s << std::any_cast<DateTime>(v).toString(DateTime::UTC);
454 } else if (t == typeid(std::shared_ptr<PropertySet>)) {
455 s << "{ ... }";
456 } else if (t == typeid(Persistable::Ptr)) {
457 s << "<Persistable>";
458 } else {
459 s << "<Unknown>";
460 }
461 }
462 if (j->second->size() > 1) {
463 s << " ]";
464 }
465 s << std::endl;
466 return s.str();
467}
468
470// Modifiers
472
473template <typename T>
474void PropertySet::set(std::string const& name, T const& value) {
476 vp->push_back(value);
477 _set(name, vp);
478}
479
480template <typename T>
481void PropertySet::set(std::string const& name, std::vector<T> const& value) {
482 if (value.empty()) return;
484 _append(*vp, value);
485 _set(name, vp);
486}
487
488void PropertySet::set(std::string const& name, char const* value) { set(name, std::string(value)); }
489
490template <typename T>
491void PropertySet::add(std::string const& name, T const& value) {
492 AnyMap::iterator i = _find(name);
493 if (i == _map.end()) {
494 set(name, value);
495 } else {
496 if (i->second->back().type() != typeid(T)) {
497 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
498 }
499 i->second->push_back(value);
500 }
501}
502
503// Specialize for shared_ptr to check for cycles.
504template <>
505void PropertySet::add<std::shared_ptr<PropertySet>>(
506 std::string const& name,
508) {
509 AnyMap::iterator i = _find(name);
510 if (i == _map.end()) {
511 set(name, value);
512 } else {
513 if (i->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
514 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
515 }
516 _cycleCheckPtr(value, name);
517 i->second->push_back(value);
518 }
519}
520
521template <typename T>
522void PropertySet::add(std::string const& name, std::vector<T> 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(T)) {
528 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
529 }
530 _append(*(i->second), value);
531 }
532}
533
534// Specialize for shared_ptr to check for cycles.
535template <>
536void PropertySet::add<std::shared_ptr<PropertySet>>(
537 std::string const& name,
539) {
540 AnyMap::iterator i = _find(name);
541 if (i == _map.end()) {
542 set(name, value);
543 } else {
544 if (i->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
545 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
546 }
547 _cycleCheckPtrVec(value, name);
548 _append(*(i->second), value);
549 }
550}
551
552void PropertySet::add(std::string const& name, char const* value) { add(name, std::string(value)); }
553
554void PropertySet::copy(
555 std::string const& dest,
556 PropertySet const& source,
557 std::string const& name,
558 bool asScalar
559) {
560 auto const sj = source._find(name);
561 if (sj == source._map.end()) {
562 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " not in source");
563 }
564 remove(dest);
565 if (asScalar) {
566 auto vp = std::make_shared<std::vector<std::any>>();
567 vp->push_back(sj->second->back());
568 _set(dest, vp);
569 } else {
570 auto vp = std::make_shared<std::vector<std::any>>(*(sj->second));
571 _set(dest, vp);
572 }
573}
574
575
576void PropertySet::combine(PropertySet const & source) {
577 std::vector<std::string> names = source.paramNames(false);
578 for (auto const& name : names) {
579 auto const sp = source._find(name);
580 _add(name, sp->second);
581 }
582}
583
584
585void PropertySet::remove(std::string const& name) {
586 std::string::size_type i = name.find('.');
587 if (_flat || i == name.npos) {
588 _map.erase(name);
589 return;
590 }
591 std::string prefix(name, 0, i);
592 AnyMap::iterator j = _map.find(prefix);
593 if (j == _map.end() || j->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
594 return;
595 }
596 auto p = std::any_cast<std::shared_ptr<PropertySet>>(j->second->back());
597 if (p.get() != 0) {
598 std::string suffix(name, i + 1);
599 p->remove(suffix);
600 }
601}
602
604// Private member functions
606
607PropertySet::AnyMap::iterator PropertySet::_find(std::string const& name) {
608 std::string::size_type i = name.find('.');
609 if (_flat || i == name.npos) {
610 return _map.find(name);
611 }
612 std::string prefix(name, 0, i);
613 AnyMap::iterator j = _map.find(prefix);
614 if (j == _map.end() || j->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
615 return _map.end();
616 }
617 auto p = std::any_cast<std::shared_ptr<PropertySet>>(j->second->back());
618 if (p.get() == 0) {
619 return _map.end();
620 }
621 std::string suffix(name, i + 1);
622 AnyMap::iterator x = p->_find(suffix);
623 if (x == p->_map.end()) {
624 return _map.end();
625 }
626 return x;
627}
628
629PropertySet::AnyMap::const_iterator PropertySet::_find(std::string const& name) const {
630 std::string::size_type i = name.find('.');
631 if (_flat || i == name.npos) {
632 return _map.find(name);
633 }
634 std::string prefix(name, 0, i);
635 auto const j = _map.find(prefix);
636 if (j == _map.end() || j->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
637 return _map.end();
638 }
639 auto p = std::any_cast<std::shared_ptr<PropertySet>>(j->second->back());
640 if (p.get() == 0) {
641 return _map.end();
642 }
643 std::string suffix(name, i + 1);
644 auto const x = p->_find(suffix);
645 if (x == p->_map.end()) {
646 return _map.end();
647 }
648 return x;
649}
650
651void PropertySet::_set(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
652 _findOrInsert(name, vp);
653}
654
655void PropertySet::_add(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
656 auto const dp = _find(name);
657 if (dp == _map.end()) {
658 _set(name, vp);
659 } else {
660 if (vp->back().type() != dp->second->back().type()) {
661 throw LSST_EXCEPT(pex::exceptions::TypeError, name + " has mismatched type");
662 }
663 // Check for cycles
664 if (vp->back().type() == typeid(std::shared_ptr<PropertySet>)) {
665 _cycleCheckAnyVec(*vp, name);
666 }
667 _append(*(dp->second), *vp);
668 }
669}
670
671void PropertySet::_findOrInsert(std::string const& name, std::shared_ptr<std::vector<std::any>> vp) {
672 if (vp->back().type() == typeid(std::shared_ptr<PropertySet>)) {
673 if (_flat) {
674 auto source = std::any_cast<std::shared_ptr<PropertySet>>(vp->back());
675 std::vector<std::string> names = source->paramNames(false);
676 for (auto const& i : names) {
677 auto const sp = source->_find(i);
678 _add(name + "." + i, sp->second);
679 }
680 return;
681 }
682
683 // Check for cycles
684 _cycleCheckAnyVec(*vp, name);
685 }
686
687 std::string::size_type i = name.find('.');
688 if (_flat || i == name.npos) {
689 _map[name] = vp;
690 return;
691 }
692 std::string prefix(name, 0, i);
693 std::string suffix(name, i + 1);
694 AnyMap::iterator j = _map.find(prefix);
695 if (j == _map.end()) {
696 auto pp = std::make_shared<PropertySet>();
697 pp->_findOrInsert(suffix, vp);
699 temp->push_back(pp);
700 _map[prefix] = temp;
701 return;
702 } else if (j->second->back().type() != typeid(std::shared_ptr<PropertySet>)) {
703 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
704 prefix + " exists but does not contain PropertySets");
705 }
706 auto p = std::any_cast<std::shared_ptr<PropertySet>>(j->second->back());
707 if (p.get() == 0) {
708 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
709 prefix + " exists but contains a null PropertySet");
710 }
711 p->_findOrInsert(suffix, vp);
712}
713
714void PropertySet::_cycleCheckPtrVec(
716 std::string const& name
717) {
718 for (auto const& i : v) {
719 _cycleCheckPtr(i, name);
720 }
721}
722
723void PropertySet::_cycleCheckAnyVec(std::vector<std::any> const& v, std::string const& name) {
724 for (auto const& i : v) {
725 _cycleCheckPtr(std::any_cast<std::shared_ptr<PropertySet>>(i), name);
726 }
727}
728
729void PropertySet::_cycleCheckPtr(std::shared_ptr<PropertySet> const & v, std::string const& name) {
730 if (v.get() == this) {
731 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
732 }
733 std::vector<std::string> sets = v->propertySetNames(false);
734 for (auto const& i : sets) {
735 if (v->getAsPropertySetPtr(i).get() == this) {
736 throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, name + " would cause a cycle");
737 }
738 }
739}
740
742 // Explicit template instantiations
744
746 // Explicit template instantiations are not well understood by doxygen.
747
748#define INSTANTIATE(t) \
749 template std::type_info const& PropertySet::typeOfT<t>(); \
750 template t PropertySet::get<t>(std::string const& name) const; \
751 template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
752 template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
753 template void PropertySet::set<t>(std::string const& name, t const& value); \
754 template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value); \
755 template void PropertySet::add<t>(std::string const& name, t const& value); \
756 template void PropertySet::add<t>(std::string const& name, std::vector<t> const& value);
757
758#define INSTANTIATE_PROPERTY_SET(t) \
759 template std::type_info const& PropertySet::typeOfT<t>(); \
760 template t PropertySet::get<t>(std::string const& name) const; \
761 template t PropertySet::get<t>(std::string const& name, t const& defaultValue) const; \
762 template std::vector<t> PropertySet::getArray<t>(std::string const& name) const; \
763 template void PropertySet::set<t>(std::string const& name, t const& value); \
764 template void PropertySet::set<t>(std::string const& name, std::vector<t> const& value);
765
766INSTANTIATE(bool)
767INSTANTIATE(char)
768INSTANTIATE(signed char)
769INSTANTIATE(unsigned char)
770INSTANTIATE(short)
771INSTANTIATE(unsigned short)
772INSTANTIATE(int)
773INSTANTIATE(unsigned int)
774INSTANTIATE(long)
775INSTANTIATE(unsigned long)
776INSTANTIATE(long long)
777INSTANTIATE(unsigned long long)
778INSTANTIATE(float)
779INSTANTIATE(double)
782INSTANTIATE_PROPERTY_SET(std::shared_ptr<PropertySet>)
783INSTANTIATE(Persistable::Ptr)
784INSTANTIATE(DateTime)
785
786} // namespace base
787} // namespace daf
788} // namespace lsst
789
table::Key< std::string > name
Definition Amplifier.cc:116
Interface for DateTime class.
#define INSTANTIATE(FROMSYS, TOSYS)
Definition Detector.cc:509
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
std::shared_ptr< RecordT > src
Definition Match.cc:48
std::string prefix
T back(T... args)
T begin(T... args)
PropertySet(bool flat=false)
Construct an empty PropertySet.
T end(T... args)
T endl(T... args)
daf::base::PropertySet * set
Definition fits.cc:931
T get(T... args)
const char * source()
Source function that allows astChannel to source from a Stream.
Definition Stream.h:224
STL namespace.
T push_back(T... args)
T remove(T... args)
T reserve(T... args)
T showpoint(T... args)
T size(T... args)
T sort(T... args)
double w
Definition CoaddPsf.cc:70
ImageT val
Definition CR.cc:146
T throw_with_nested(T... args)