aqnwb 0.4.0
Loading...
Searching...
No Matches
RegisteredType.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <filesystem>
4#include <functional>
5#include <memory>
6#include <string>
7#include <unordered_map>
8#include <unordered_set>
9
10#include "Types.hpp"
11#include "Utils.hpp"
12#include "io/BaseIO.hpp"
13#include "io/ReadIO.hpp"
14
15namespace AQNWB
16{
17namespace NWB
18{
19
23constexpr auto AttributeField = AQNWB::Types::StorageObjectType::Attribute;
24
28constexpr auto DatasetField = AQNWB::Types::StorageObjectType::Dataset;
29
47class RegisteredType : public std::enable_shared_from_this<RegisteredType>
48{
49public:
53 virtual ~RegisteredType();
54
59 inline const std::string& getPath() const { return m_path; }
60
68 inline std::string getName() const
69 {
70 return std::filesystem::path(m_path).filename().string();
71 }
72
77 inline std::shared_ptr<AQNWB::IO::BaseIO> getIO() const
78 {
79 auto ioPtr = m_io.lock();
80 return ioPtr;
81 }
82
89
95 inline bool isRegisteredRecordingObject() const
96 {
98 }
99
116
133
140 [[deprecated(
141 "The cache is owned by the I/O so there should be no need to access it "
142 "via RegisteredType. Use getIO()->getRecordingDataCache() instead.")]]
143 inline const std::unordered_map<std::string,
144 std::shared_ptr<IO::BaseRecordingData>>&
146 {
147 if (auto io = getIO()) {
148 return io->getRecordingDataCache();
149 }
150 throw std::runtime_error(
151 "RegisteredType::getCacheRecordingData: IO object is not available");
152 }
153
161 [[deprecated(
162 "The cache is owned by the I/O so there should be no need to access it "
163 "via RegisteredType. Use getIO()->clearRecordingDataCache() instead.")]]
164 inline virtual void clearRecordingDataCache()
165 {
166 if (auto io = getIO()) {
167 io->clearRecordingDataCache();
168 }
169 }
170
182 static std::unordered_set<std::string>& getRegistry();
183
195 static std::unordered_map<
196 std::string,
197 std::pair<std::function<std::shared_ptr<RegisteredType>(
198 const std::string&, std::shared_ptr<AQNWB::IO::BaseIO>)>,
199 std::pair<std::string, std::string>>>&
201
221 static std::shared_ptr<RegisteredType> create(
222 const std::string& fullClassName,
223 const std::string& path,
224 std::shared_ptr<IO::BaseIO> io,
225 bool fallbackToBase = false);
226
248 static std::shared_ptr<AQNWB::NWB::RegisteredType> create(
249 const std::string& path,
250 std::shared_ptr<IO::BaseIO> io,
251 bool fallbackToBase = false);
252
268 template<typename T>
269 static inline std::shared_ptr<T> create(const std::string& path,
270 std::shared_ptr<AQNWB::IO::BaseIO> io)
271 {
272 static_assert(std::is_base_of<RegisteredType, T>::value,
273 "T must be a derived class of RegisteredType");
274 auto existing = getExistingRecordingObject(path, io);
275 if (existing) {
276 auto casted = std::dynamic_pointer_cast<T>(existing);
277 if (casted) {
278 return casted;
279 }
280 std::cerr << "RegisteredType::create: cached object at path " << path
281 << " has type " << existing->getFullTypeName()
282 << ", which does not match the requested type." << std::endl;
283 return nullptr;
284 }
285 auto result = std::shared_ptr<T>(new T(path, io));
286 result->registerRecordingObject();
287 return result;
288 }
289
300 virtual std::string getTypeName() const;
301
313 virtual std::string getNamespace() const;
314
323 inline std::string getFullTypeName() const
324 {
325 return (getNamespace() + "::" + getTypeName());
326 }
327
348 template<StorageObjectType SOT,
349 typename VTYPE,
350 typename std::enable_if<Types::IsDataStorageObjectType<SOT>::value,
351 int>::type = 0>
352 inline std::unique_ptr<AQNWB::IO::ReadDataWrapper<SOT, VTYPE>> readField(
353 const std::string& fieldPath) const
354 {
355 auto ioPtr = getIO();
356 if (!ioPtr) {
357 std::cerr << "IO object has been deleted. Can't read field: " << fieldPath
358 << std::endl;
359 return nullptr;
360 }
361 return std::make_unique<AQNWB::IO::ReadDataWrapper<SOT, VTYPE>>(
362 ioPtr, AQNWB::mergePaths(m_path, fieldPath));
363 }
364
373 inline std::shared_ptr<AQNWB::NWB::RegisteredType> readField(
374 const std::string& fieldPath) const
375 {
376 auto ioPtr = getIO();
377 if (!ioPtr) {
378 std::cerr << "IO object has been deleted. Can't read field: " << fieldPath
379 << std::endl;
380 return nullptr;
381 }
382 return this->create(AQNWB::mergePaths(m_path, fieldPath), ioPtr);
383 }
384
403 virtual std::unordered_map<std::string, std::string> findOwnedTypes(
404 const std::unordered_set<std::string>& types = {},
405 const AQNWB::IO::SearchMode& search_mode =
407
419 virtual std::string findOwnedObject(const std::string& name) const;
420
421protected:
428 static std::shared_ptr<RegisteredType> getExistingRecordingObject(
429 const std::string& path, std::shared_ptr<AQNWB::IO::BaseIO> io);
430
440 RegisteredType(const std::string& path,
441 std::shared_ptr<AQNWB::IO::BaseIO> io);
442
445 static const std::string m_defaultUnregisteredGroupTypeClass;
446
450
460 static void registerSubclass(
461 const std::string& fullClassName,
462 std::function<std::shared_ptr<RegisteredType>(
463 const std::string&, std::shared_ptr<AQNWB::IO::BaseIO>)>
464 factoryFunction,
465 const std::string& typeName,
466 const std::string& typeNamespace);
467
471 std::string m_path;
472
483 std::weak_ptr<IO::BaseIO> m_io;
484};
485
504#define REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE_VAR, TYPENAME) \
505 friend class AQNWB::NWB::RegisteredType; /* base can call constructor */ \
506protected: \
507 using BASE::BASE; /* inherit from immediate base */ \
508public: \
509 static bool registerSubclass() \
510 { \
511 AQNWB::NWB::RegisteredType::registerSubclass( \
512 std::string(NAMESPACE_VAR) + "::" + #T, \
513 [](const std::string& path, std::shared_ptr<AQNWB::IO::BaseIO> io) \
514 -> std::shared_ptr<AQNWB::NWB::RegisteredType> \
515 { return RegisteredType::create<T>(path, io); }, \
516 TYPENAME, \
517 NAMESPACE_VAR); \
518 return true; \
519 } \
520 static bool registered_; \
521 virtual std::string getTypeName() const override \
522 { \
523 return TYPENAME; \
524 } \
525 virtual std::string getNamespace() const override \
526 { \
527 return NAMESPACE_VAR; \
528 } \
529 static std::shared_ptr<T> create(const std::string& path, \
530 std::shared_ptr<AQNWB::IO::BaseIO> io) \
531 { \
532 return RegisteredType::create<T>(path, io); \
533 }
534
547#define REGISTER_SUBCLASS(T, BASE, NAMESPACE) \
548 REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE, #T)
549
559#define REGISTER_SUBCLASS_IMPL(T) bool T::registered_ = T::registerSubclass();
560
580#define DEFINE_ATTRIBUTE_FIELD(name, default_type, fieldPath, description) \
581 \
589 template<typename VTYPE = default_type> \
590 inline std::unique_ptr< \
591 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>> \
592 name() const \
593 { \
594 auto ioPtr = getIO(); \
595 if (!ioPtr) { \
596 std::cerr << "IO object has been deleted. Can't read field: " \
597 << fieldPath << std::endl; \
598 return nullptr; \
599 } \
600 return std::make_unique< \
601 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>>( \
602 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
603 }
604
626#define DEFINE_DATASET_FIELD( \
627 readName, writeName, default_type, fieldPath, description) \
628 \
636 template<typename VTYPE = default_type> \
637 inline std::unique_ptr< \
638 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>> \
639 readName() const \
640 { \
641 auto ioPtr = getIO(); \
642 if (!ioPtr) { \
643 std::cerr << "IO object has been deleted. Can't read field: " \
644 << fieldPath << std::endl; \
645 return nullptr; \
646 } \
647 return std::make_unique< \
648 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>>( \
649 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
650 } \
651 \
664 inline std::shared_ptr<AQNWB::IO::BaseRecordingData> writeName(bool reset = \
665 false) \
666 { \
667 std::string fullPath = AQNWB::mergePaths(m_path, fieldPath); \
668 auto ioPtr = getIO(); \
669 if (!ioPtr) { \
670 std::cerr << "IO object has been deleted. Can't access: " << fullPath \
671 << std::endl; \
672 return nullptr; \
673 } \
674 return ioPtr->getDataSet(fullPath, reset); \
675 }
676
686
698#define DEFINE_REGISTERED_FIELD(name, registeredType, fieldPath, description) \
699 \
711 template<typename RTYPE = registeredType> \
712 inline std::shared_ptr<RTYPE> name() const \
713 { \
714 std::string objectPath = AQNWB::mergePaths(m_path, fieldPath); \
715 auto ioPtr = getIO(); \
716 if (ioPtr != nullptr) { \
717 if (ioPtr->objectExists(objectPath)) { \
718 return RTYPE::create(objectPath, ioPtr); \
719 } \
720 } \
721 return nullptr; \
722 }
723
748#define DEFINE_UNNAMED_REGISTERED_FIELD( \
749 readName, writeName, registeredType, fieldPrefixPath, description) \
750 \
763 template<typename RTYPE = registeredType> \
764 inline std::shared_ptr<RTYPE> readName(const std::string& objectName) const \
765 { \
766 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
767 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
768 auto ioPtr = getIO(); \
769 if (!ioPtr) { \
770 std::cerr << "IO object has been deleted. Can't read field: " \
771 << objectPath << std::endl; \
772 return nullptr; \
773 } \
774 if (ioPtr->objectExists(objectPath)) { \
775 return RTYPE::create(objectPath, ioPtr); \
776 } \
777 return nullptr; \
778 } \
779 \
793 template<typename RTYPE = registeredType> \
794 inline std::shared_ptr<RTYPE> writeName(const std::string& objectName) const \
795 { \
796 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
797 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
798 auto ioPtr = getIO(); \
799 if (!ioPtr) { \
800 std::cerr << "IO object has been deleted. Can't create field: " \
801 << objectPath << std::endl; \
802 return nullptr; \
803 } \
804 return RTYPE::create(objectPath, ioPtr); \
805 }
806
828#define DEFINE_REFERENCED_REGISTERED_FIELD( \
829 name, registeredType, fieldPath, description) \
830 \
842 template<typename RTYPE = registeredType> \
843 inline std::shared_ptr<RTYPE> name() const \
844 { \
845 try { \
846 std::string attrPath = AQNWB::mergePaths(m_path, fieldPath); \
847 auto ioPtr = getIO(); \
848 if (ioPtr != nullptr) { \
849 std::string objectPath = ioPtr->readReferenceAttribute(attrPath); \
850 if (ioPtr->objectExists(objectPath)) { \
851 return RTYPE::create(objectPath, ioPtr); \
852 } \
853 } \
854 } catch (const std::exception& e) { \
855 std::cerr << "WARNING Error occurred in " << #name << " " << e.what() \
856 << std::endl; \
857 return nullptr; \
858 } \
859 return nullptr; \
860 }
861
862} // namespace NWB
863} // namespace AQNWB
AQNWB::Types::StorageObjectType StorageObjectType
Definition BaseIO.hpp:20
AQNWB::Types::SizeType SizeType
Definition Channel.hpp:8
std::shared_ptr< AQNWB::NWB::RegisteredType > readField(const std::string &fieldPath) const
Read a field that is itself a RegisteredType.
Definition RegisteredType.hpp:373
const std::string & getPath() const
Gets the path of the registered type.
Definition RegisteredType.hpp:59
std::string getFullTypeName() const
Get the full name of the type, i.e., namespace::typename.
Definition RegisteredType.hpp:323
virtual std::string getTypeName() const
Get the name of the class type.
Definition RegisteredType.cpp:63
static std::shared_ptr< T > create(const std::string &path, std::shared_ptr< AQNWB::IO::BaseIO > io)
Create or retrieve a canonical instance of a RegisteredType subtype.
Definition RegisteredType.hpp:269
std::string m_path
The path of the registered type.
Definition RegisteredType.hpp:471
static const std::string m_defaultUnregisteredDatasetTypeClass
Save the default RegisteredType to use for reading Dataset types that are not registered.
Definition RegisteredType.hpp:449
virtual std::string getNamespace() const
Get the schema namespace of the class type.
Definition RegisteredType.cpp:70
static std::shared_ptr< RegisteredType > create(const std::string &fullClassName, const std::string &path, std::shared_ptr< IO::BaseIO > io, bool fallbackToBase=false)
Create or retrieve the canonical instance of a registered subclass.
Definition RegisteredType.cpp:87
std::weak_ptr< IO::BaseIO > m_io
A weak pointer to the IO object.
Definition RegisteredType.hpp:483
virtual std::unordered_map< std::string, std::string > findOwnedTypes(const std::unordered_set< std::string > &types={}, const AQNWB::IO::SearchMode &search_mode=AQNWB::IO::SearchMode::STOP_ON_TYPE) const
Find all typed objects that are owned by this object, i.e., objects that have a neurodata_type and na...
Definition RegisteredType.cpp:186
SizeType registerRecordingObject()
Register this RegisteredType object with the RecordingObjects manager object of the I/O.
Definition RegisteredType.cpp:161
std::string getName() const
Get the name of the object.
Definition RegisteredType.hpp:68
RegisteredType(const std::string &path, std::shared_ptr< AQNWB::IO::BaseIO > io)
Constructor.
Definition RegisteredType.cpp:18
virtual AQNWB::Types::Status finalize()
Finalize the RegisteredType object.
Definition RegisteredType.cpp:181
static void registerSubclass(const std::string &fullClassName, std::function< std::shared_ptr< RegisteredType >(const std::string &, std::shared_ptr< AQNWB::IO::BaseIO >)> factoryFunction, const std::string &typeName, const std::string &typeNamespace)
Register a subclass name and its factory function in the registry.
Definition RegisteredType.cpp:49
std::shared_ptr< AQNWB::IO::BaseIO > getIO() const
Get a shared pointer to the IO object.
Definition RegisteredType.hpp:77
virtual void clearRecordingDataCache()
Clear the BaseRecordingData object cache to reset the recording state.
Definition RegisteredType.hpp:164
static std::shared_ptr< RegisteredType > getExistingRecordingObject(const std::string &path, std::shared_ptr< AQNWB::IO::BaseIO > io)
Helper to get an existing recording object from the IO object.
Definition RegisteredType.cpp:75
static std::unordered_set< std::string > & getRegistry()
Get the registry of subclass names.
Definition RegisteredType.cpp:27
virtual ~RegisteredType()
Destructor.
Definition RegisteredType.cpp:25
SizeType getRecordingObjectIndex() const
Get the index of this object in m_io->m_recording_objects.
Definition RegisteredType.cpp:212
static const std::string m_defaultUnregisteredGroupTypeClass
Save the default RegisteredType to use for reading Group types that are not registered.
Definition RegisteredType.hpp:445
static std::unordered_map< std::string, std::pair< std::function< std::shared_ptr< RegisteredType >(const std::string &, std::shared_ptr< AQNWB::IO::BaseIO >)>, std::pair< std::string, std::string > > > & getFactoryMap()
Get the factory map for creating instances of subclasses.
Definition RegisteredType.cpp:38
const std::unordered_map< std::string, std::shared_ptr< IO::BaseRecordingData > > & getCacheRecordingData() const
Get the cache of BaseRecordingData objects.
Definition RegisteredType.hpp:145
virtual std::string findOwnedObject(const std::string &name) const
Find the first object owned by this object whose path ends with the given name.
Definition RegisteredType.cpp:200
std::unique_ptr< AQNWB::IO::ReadDataWrapper< SOT, VTYPE > > readField(const std::string &fieldPath) const
Support reading of arbitrary fields by their relative path.
Definition RegisteredType.hpp:352
bool isRegisteredRecordingObject() const
Check if this RegisteredType object is registered in the RecordingObjects manager object of the I/O.
Definition RegisteredType.hpp:95
SearchMode
Enum class for specifying the search mode for findTypes.
Definition BaseIO.hpp:229
@ STOP_ON_TYPE
Stop searching inside an object once a matching type is found.
Definition BaseIO.hpp:233
Namespace for all classes related to the NWB data standard.
constexpr auto AttributeField
Alias for AQNWB::Types::StorageObjectType::Attribute.
Definition RegisteredType.hpp:23
constexpr auto DatasetField
Alias for AQNWB::Types::StorageObjectType::Dataset.
Definition RegisteredType.hpp:28
Status
Represents the status of an operation.
Definition Types.hpp:29
The main namespace for AqNWB.
Definition Channel.hpp:11
static std::string mergePaths(const std::string &path1, const std::string &path2)
Merge two paths into a single path, handling extra trailing and starting "/".
Definition Utils.hpp:264
static bool isValidIndex(SizeType index)
Check if a SizeType index is valid (i.e., not equal to SizeTypeNotSet).
Definition Utils.hpp:362