aqnwb 0.2.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 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
138 inline const std::unordered_map<std::string,
139 std::shared_ptr<IO::BaseRecordingData>>&
141 {
142 return this->m_recordingDataCache;
143 }
144
149 inline virtual void clearRecordingDataCache()
150 {
151 this->m_recordingDataCache.clear();
152 }
153
165 static std::unordered_set<std::string>& getRegistry();
166
178 static std::unordered_map<
179 std::string,
180 std::pair<std::function<std::shared_ptr<RegisteredType>(
181 const std::string&, std::shared_ptr<AQNWB::IO::BaseIO>)>,
182 std::pair<std::string, std::string>>>&
184
200 static std::shared_ptr<RegisteredType> create(
201 const std::string& fullClassName,
202 const std::string& path,
203 std::shared_ptr<IO::BaseIO> io,
204 bool fallbackToBase = false);
205
226 static std::shared_ptr<AQNWB::NWB::RegisteredType> create(
227 const std::string& path,
228 std::shared_ptr<IO::BaseIO> io,
229 bool fallbackToBase = false);
230
240 template<typename T>
241 static inline std::shared_ptr<T> create(const std::string& path,
242 std::shared_ptr<AQNWB::IO::BaseIO> io)
243 {
244 static_assert(std::is_base_of<RegisteredType, T>::value,
245 "T must be a derived class of RegisteredType");
246 auto result = std::shared_ptr<T>(new T(path, io));
247 result->registerRecordingObject();
248 return result;
249 }
250
261 virtual std::string getTypeName() const;
262
274 virtual std::string getNamespace() const;
275
284 inline std::string getFullTypeName() const
285 {
286 return (getNamespace() + "::" + getTypeName());
287 }
288
309 template<StorageObjectType SOT,
310 typename VTYPE,
311 typename std::enable_if<Types::IsDataStorageObjectType<SOT>::value,
312 int>::type = 0>
313 inline std::unique_ptr<AQNWB::IO::ReadDataWrapper<SOT, VTYPE>> readField(
314 const std::string& fieldPath) const
315 {
316 auto ioPtr = getIO();
317 if (!ioPtr) {
318 std::cerr << "IO object has been deleted. Can't read field: " << fieldPath
319 << std::endl;
320 return nullptr;
321 }
322 return std::make_unique<AQNWB::IO::ReadDataWrapper<SOT, VTYPE>>(
323 ioPtr, AQNWB::mergePaths(m_path, fieldPath));
324 }
325
334 inline std::shared_ptr<AQNWB::NWB::RegisteredType> readField(
335 const std::string& fieldPath) const
336 {
337 auto ioPtr = getIO();
338 if (!ioPtr) {
339 std::cerr << "IO object has been deleted. Can't read field: " << fieldPath
340 << std::endl;
341 return nullptr;
342 }
343 return this->create(AQNWB::mergePaths(m_path, fieldPath), ioPtr);
344 }
345
364 virtual std::unordered_map<std::string, std::string> findOwnedTypes(
365 const std::unordered_set<std::string>& types = {},
366 const AQNWB::IO::SearchMode& search_mode =
368
369protected:
379 RegisteredType(const std::string& path,
380 std::shared_ptr<AQNWB::IO::BaseIO> io);
381
384 static const std::string m_defaultUnregisteredGroupTypeClass;
385
389
399 static void registerSubclass(
400 const std::string& fullClassName,
401 std::function<std::shared_ptr<RegisteredType>(
402 const std::string&, std::shared_ptr<AQNWB::IO::BaseIO>)>
403 factoryFunction,
404 const std::string& typeName,
405 const std::string& typeNamespace);
406
410 std::string m_path;
411
422 std::weak_ptr<IO::BaseIO> m_io;
423
436 std::unordered_map<std::string, std::shared_ptr<IO::BaseRecordingData>>
438};
439
458#define REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE_VAR, TYPENAME) \
459 friend class AQNWB::NWB::RegisteredType; /* base can call constructor */ \
460protected: \
461 using BASE::BASE; /* inherit from immediate base */ \
462public: \
463 static bool registerSubclass() \
464 { \
465 AQNWB::NWB::RegisteredType::registerSubclass( \
466 std::string(NAMESPACE_VAR) + "::" + #T, \
467 [](const std::string& path, std::shared_ptr<AQNWB::IO::BaseIO> io) \
468 -> std::shared_ptr<AQNWB::NWB::RegisteredType> \
469 { return RegisteredType::create<T>(path, io); }, \
470 TYPENAME, \
471 NAMESPACE_VAR); \
472 return true; \
473 } \
474 static bool registered_; \
475 virtual std::string getTypeName() const override \
476 { \
477 return TYPENAME; \
478 } \
479 virtual std::string getNamespace() const override \
480 { \
481 return NAMESPACE_VAR; \
482 } \
483 static std::shared_ptr<T> create(const std::string& path, \
484 std::shared_ptr<AQNWB::IO::BaseIO> io) \
485 { \
486 return RegisteredType::create<T>(path, io); \
487 }
488
501#define REGISTER_SUBCLASS(T, BASE, NAMESPACE) \
502 REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE, #T)
503
513#define REGISTER_SUBCLASS_IMPL(T) bool T::registered_ = T::registerSubclass();
514
534#define DEFINE_ATTRIBUTE_FIELD(name, default_type, fieldPath, description) \
535 \
543 template<typename VTYPE = default_type> \
544 inline std::unique_ptr< \
545 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>> \
546 name() const \
547 { \
548 auto ioPtr = getIO(); \
549 if (!ioPtr) { \
550 std::cerr << "IO object has been deleted. Can't read field: " \
551 << fieldPath << std::endl; \
552 return nullptr; \
553 } \
554 return std::make_unique< \
555 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>>( \
556 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
557 }
558
580#define DEFINE_DATASET_FIELD( \
581 readName, writeName, default_type, fieldPath, description) \
582 \
590 template<typename VTYPE = default_type> \
591 inline std::unique_ptr< \
592 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>> \
593 readName() const \
594 { \
595 auto ioPtr = getIO(); \
596 if (!ioPtr) { \
597 std::cerr << "IO object has been deleted. Can't read field: " \
598 << fieldPath << std::endl; \
599 return nullptr; \
600 } \
601 return std::make_unique< \
602 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>>( \
603 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
604 } \
605 \
618 inline std::shared_ptr<AQNWB::IO::BaseRecordingData> writeName(bool reset = \
619 false) \
620 { \
621 std::string fullPath = AQNWB::mergePaths(m_path, fieldPath); \
622 if (!reset) { \
623 /* Check if the dataset is already in the cache */ \
624 auto it = m_recordingDataCache.find(fullPath); \
625 if (it != m_recordingDataCache.end()) { \
626 return it->second; \
627 } \
628 } \
629 /* Get the dataset from IO and cache it */ \
630 auto ioPtr = getIO(); \
631 if (!ioPtr) { \
632 std::cerr << "IO object has been deleted. Can't access: " << fullPath \
633 << std::endl; \
634 return nullptr; \
635 } \
636 auto dataset = ioPtr->getDataSet(fullPath); \
637 if (dataset) { \
638 m_recordingDataCache[fullPath] = dataset; \
639 } \
640 return dataset; \
641 }
642
652
664#define DEFINE_REGISTERED_FIELD(name, registeredType, fieldPath, description) \
665 \
677 template<typename RTYPE = registeredType> \
678 inline std::shared_ptr<RTYPE> name() const \
679 { \
680 std::string objectPath = AQNWB::mergePaths(m_path, fieldPath); \
681 auto ioPtr = getIO(); \
682 if (ioPtr != nullptr) { \
683 if (ioPtr->objectExists(objectPath)) { \
684 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
685 } \
686 } \
687 return nullptr; \
688 }
689
714#define DEFINE_UNNAMED_REGISTERED_FIELD( \
715 readName, writeName, registeredType, fieldPrefixPath, description) \
716 \
729 template<typename RTYPE = registeredType> \
730 inline std::shared_ptr<RTYPE> readName(const std::string& objectName) const \
731 { \
732 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
733 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
734 auto ioPtr = getIO(); \
735 if (!ioPtr) { \
736 std::cerr << "IO object has been deleted. Can't read field: " \
737 << objectPath << std::endl; \
738 return nullptr; \
739 } \
740 if (ioPtr->objectExists(objectPath)) { \
741 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
742 } \
743 return nullptr; \
744 } \
745 \
759 template<typename RTYPE = registeredType> \
760 inline std::shared_ptr<RTYPE> writeName(const std::string& objectName) const \
761 { \
762 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
763 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
764 auto ioPtr = getIO(); \
765 if (!ioPtr) { \
766 std::cerr << "IO object has been deleted. Can't create field: " \
767 << objectPath << std::endl; \
768 return nullptr; \
769 } \
770 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
771 }
772
794#define DEFINE_REFERENCED_REGISTERED_FIELD( \
795 name, registeredType, fieldPath, description) \
796 \
808 template<typename RTYPE = registeredType> \
809 inline std::shared_ptr<RTYPE> name() const \
810 { \
811 try { \
812 std::string attrPath = AQNWB::mergePaths(m_path, fieldPath); \
813 auto ioPtr = getIO(); \
814 if (ioPtr != nullptr) { \
815 std::string objectPath = ioPtr->readReferenceAttribute(attrPath); \
816 if (ioPtr->objectExists(objectPath)) { \
817 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
818 } \
819 } \
820 } catch (const std::exception& e) { \
821 std::cerr << "WARNING Error occurred in " << #name << " " << e.what() \
822 << std::endl; \
823 return nullptr; \
824 } \
825 return nullptr; \
826 }
827
828} // namespace NWB
829} // namespace AQNWB
AQNWB::Types::StorageObjectType StorageObjectType
Definition BaseIO.hpp:21
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:334
std::string getFullTypeName() const
Get the full name of the type, i.e., namespace::typename.
Definition RegisteredType.hpp:284
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)
Factory method to create an instance of a subclass of RegisteredType by type.
Definition RegisteredType.hpp:241
std::string m_path
The path of the registered type.
Definition RegisteredType.hpp:410
static const std::string m_defaultUnregisteredDatasetTypeClass
Save the default RegisteredType to use for reading Dataset types that are not registered.
Definition RegisteredType.hpp:388
std::unordered_map< std::string, std::shared_ptr< IO::BaseRecordingData > > m_recordingDataCache
Cache for BaseRecordingData objects for datasets to retain recording state.
Definition RegisteredType.hpp:437
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 an instance of a registered subclass by name.
Definition RegisteredType.cpp:75
std::weak_ptr< IO::BaseIO > m_io
A weak pointer to the IO object.
Definition RegisteredType.hpp:422
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:153
SizeType registerRecordingObject()
Register this RegisteredType object with the RecordingObjects manager object of the I/O.
Definition RegisteredType.cpp:128
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:148
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::string getPath() const
Gets the path of the registered type.
Definition RegisteredType.hpp:59
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:149
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:167
static const std::string m_defaultUnregisteredGroupTypeClass
Save the default RegisteredType to use for reading Group types that are not registered.
Definition RegisteredType.hpp:384
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:140
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:313
bool isRegisteredRecordingObject() const
Check if this RegisteredType object is registered in the RecordingObjects manager object of the I/O.
Definition RegisteredType.hpp:95
Status
Represents the status of an operation.
Definition Types.hpp:23
SearchMode
Enum class for specifying the search mode for findTypes.
Definition BaseIO.hpp:156
@ STOP_ON_TYPE
Stop searching inside an object once a matching type is found.
Definition BaseIO.hpp:160
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
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:112
static bool isValidIndex(SizeType index)
Check if a SizeType index is valid (i.e., not equal to SizeTypeNotSet).
Definition Utils.hpp:210