aqnwb 0.3.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
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
380 virtual std::string findOwnedObject(const std::string& name) const;
381
382protected:
392 RegisteredType(const std::string& path,
393 std::shared_ptr<AQNWB::IO::BaseIO> io);
394
397 static const std::string m_defaultUnregisteredGroupTypeClass;
398
402
412 static void registerSubclass(
413 const std::string& fullClassName,
414 std::function<std::shared_ptr<RegisteredType>(
415 const std::string&, std::shared_ptr<AQNWB::IO::BaseIO>)>
416 factoryFunction,
417 const std::string& typeName,
418 const std::string& typeNamespace);
419
423 std::string m_path;
424
435 std::weak_ptr<IO::BaseIO> m_io;
436
449 std::unordered_map<std::string, std::shared_ptr<IO::BaseRecordingData>>
451};
452
471#define REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE_VAR, TYPENAME) \
472 friend class AQNWB::NWB::RegisteredType; /* base can call constructor */ \
473protected: \
474 using BASE::BASE; /* inherit from immediate base */ \
475public: \
476 static bool registerSubclass() \
477 { \
478 AQNWB::NWB::RegisteredType::registerSubclass( \
479 std::string(NAMESPACE_VAR) + "::" + #T, \
480 [](const std::string& path, std::shared_ptr<AQNWB::IO::BaseIO> io) \
481 -> std::shared_ptr<AQNWB::NWB::RegisteredType> \
482 { return RegisteredType::create<T>(path, io); }, \
483 TYPENAME, \
484 NAMESPACE_VAR); \
485 return true; \
486 } \
487 static bool registered_; \
488 virtual std::string getTypeName() const override \
489 { \
490 return TYPENAME; \
491 } \
492 virtual std::string getNamespace() const override \
493 { \
494 return NAMESPACE_VAR; \
495 } \
496 static std::shared_ptr<T> create(const std::string& path, \
497 std::shared_ptr<AQNWB::IO::BaseIO> io) \
498 { \
499 return RegisteredType::create<T>(path, io); \
500 }
501
514#define REGISTER_SUBCLASS(T, BASE, NAMESPACE) \
515 REGISTER_SUBCLASS_WITH_TYPENAME(T, BASE, NAMESPACE, #T)
516
526#define REGISTER_SUBCLASS_IMPL(T) bool T::registered_ = T::registerSubclass();
527
547#define DEFINE_ATTRIBUTE_FIELD(name, default_type, fieldPath, description) \
548 \
556 template<typename VTYPE = default_type> \
557 inline std::unique_ptr< \
558 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>> \
559 name() const \
560 { \
561 auto ioPtr = getIO(); \
562 if (!ioPtr) { \
563 std::cerr << "IO object has been deleted. Can't read field: " \
564 << fieldPath << std::endl; \
565 return nullptr; \
566 } \
567 return std::make_unique< \
568 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::AttributeField, VTYPE>>( \
569 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
570 }
571
593#define DEFINE_DATASET_FIELD( \
594 readName, writeName, default_type, fieldPath, description) \
595 \
603 template<typename VTYPE = default_type> \
604 inline std::unique_ptr< \
605 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>> \
606 readName() const \
607 { \
608 auto ioPtr = getIO(); \
609 if (!ioPtr) { \
610 std::cerr << "IO object has been deleted. Can't read field: " \
611 << fieldPath << std::endl; \
612 return nullptr; \
613 } \
614 return std::make_unique< \
615 AQNWB::IO::ReadDataWrapper<AQNWB::NWB::DatasetField, VTYPE>>( \
616 ioPtr, AQNWB::mergePaths(m_path, fieldPath)); \
617 } \
618 \
631 inline std::shared_ptr<AQNWB::IO::BaseRecordingData> writeName(bool reset = \
632 false) \
633 { \
634 std::string fullPath = AQNWB::mergePaths(m_path, fieldPath); \
635 if (!reset) { \
636 /* Check if the dataset is already in the cache */ \
637 auto it = m_recordingDataCache.find(fullPath); \
638 if (it != m_recordingDataCache.end()) { \
639 return it->second; \
640 } \
641 } \
642 /* Get the dataset from IO and cache it */ \
643 auto ioPtr = getIO(); \
644 if (!ioPtr) { \
645 std::cerr << "IO object has been deleted. Can't access: " << fullPath \
646 << std::endl; \
647 return nullptr; \
648 } \
649 auto dataset = ioPtr->getDataSet(fullPath); \
650 if (dataset) { \
651 m_recordingDataCache[fullPath] = dataset; \
652 } \
653 return dataset; \
654 }
655
665
677#define DEFINE_REGISTERED_FIELD(name, registeredType, fieldPath, description) \
678 \
690 template<typename RTYPE = registeredType> \
691 inline std::shared_ptr<RTYPE> name() const \
692 { \
693 std::string objectPath = AQNWB::mergePaths(m_path, fieldPath); \
694 auto ioPtr = getIO(); \
695 if (ioPtr != nullptr) { \
696 if (ioPtr->objectExists(objectPath)) { \
697 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
698 } \
699 } \
700 return nullptr; \
701 }
702
727#define DEFINE_UNNAMED_REGISTERED_FIELD( \
728 readName, writeName, registeredType, fieldPrefixPath, description) \
729 \
742 template<typename RTYPE = registeredType> \
743 inline std::shared_ptr<RTYPE> readName(const std::string& objectName) const \
744 { \
745 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
746 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
747 auto ioPtr = getIO(); \
748 if (!ioPtr) { \
749 std::cerr << "IO object has been deleted. Can't read field: " \
750 << objectPath << std::endl; \
751 return nullptr; \
752 } \
753 if (ioPtr->objectExists(objectPath)) { \
754 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
755 } \
756 return nullptr; \
757 } \
758 \
772 template<typename RTYPE = registeredType> \
773 inline std::shared_ptr<RTYPE> writeName(const std::string& objectName) const \
774 { \
775 std::string prefixPath = AQNWB::mergePaths(m_path, fieldPrefixPath); \
776 std::string objectPath = AQNWB::mergePaths(prefixPath, objectName); \
777 auto ioPtr = getIO(); \
778 if (!ioPtr) { \
779 std::cerr << "IO object has been deleted. Can't create field: " \
780 << objectPath << std::endl; \
781 return nullptr; \
782 } \
783 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
784 }
785
807#define DEFINE_REFERENCED_REGISTERED_FIELD( \
808 name, registeredType, fieldPath, description) \
809 \
821 template<typename RTYPE = registeredType> \
822 inline std::shared_ptr<RTYPE> name() const \
823 { \
824 try { \
825 std::string attrPath = AQNWB::mergePaths(m_path, fieldPath); \
826 auto ioPtr = getIO(); \
827 if (ioPtr != nullptr) { \
828 std::string objectPath = ioPtr->readReferenceAttribute(attrPath); \
829 if (ioPtr->objectExists(objectPath)) { \
830 return RegisteredType::create<RTYPE>(objectPath, ioPtr); \
831 } \
832 } \
833 } catch (const std::exception& e) { \
834 std::cerr << "WARNING Error occurred in " << #name << " " << e.what() \
835 << std::endl; \
836 return nullptr; \
837 } \
838 return nullptr; \
839 }
840
841} // namespace NWB
842} // 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:334
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: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:423
static const std::string m_defaultUnregisteredDatasetTypeClass
Save the default RegisteredType to use for reading Dataset types that are not registered.
Definition RegisteredType.hpp:401
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:450
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:435
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::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:179
static const std::string m_defaultUnregisteredGroupTypeClass
Save the default RegisteredType to use for reading Group types that are not registered.
Definition RegisteredType.hpp:397
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
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:167
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:25
SearchMode
Enum class for specifying the search mode for findTypes.
Definition BaseIO.hpp:157
@ STOP_ON_TYPE
Stop searching inside an object once a matching type is found.
Definition BaseIO.hpp:161
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:242
static bool isValidIndex(SizeType index)
Check if a SizeType index is valid (i.e., not equal to SizeTypeNotSet).
Definition Utils.hpp:340