/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ /*========================================================================= * * Portions of this file are subject to the VTK Toolkit Version 3 copyright. * * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen * * For complete copyright, license and disclaimer of warranty information * please refer to the NOTICE file at the top of the ITK source tree. * *=========================================================================*/ #ifndef itkMetaDataObject_h #define itkMetaDataObject_h #include "itkMetaDataDictionary.h" #include "itkMacro.h" #include "itkArray.h" #include "itkMatrix.h" #include namespace itk { /** * \class MetaDataObject * \brief Allows arbitrary data types to be stored as MetaDataObjectBase types, * and to be stored in a MetaDataDictionary. * * \author Hans J. Johnson * * The MetaDataObject class is a templated class that * is a specialization of the MetaDataObjectBase type. * This class allows arbitrary data types to be * stored as MetaDataObjectBase types, and to be stored in * a MetaDataDictionary. * * Any class or built in type that has valid copy constructor and operator= * can be wrapped directly with this simple template type. * * Classes or built in types that do not have valid copy constructors or operator= * implemented will have to implement those functions by deriving from MetaDataObject * and redefining the copy constructor and initializing constructor and the Get/Set functions * to work around those deficiencies. * * The behavior of the MetaDataObject::Print() function has many plausible * application dependent implementations. The default implementation prints the * string "[UNKNOWN PRINT CHARACTERISTICS]" that works for all possible * MetaDataObject types. * * The application developer may overload the default implementation to provide * a specialized Print() characteristics to produce results desirable for their application. * A set of very crude Macros {NATIVE_TYPE_METADATAPRINT, ITK_OBJECT_TYPE_METADATAPRINT_1COMMA, * ITK_IMAGE_TYPE_METADATAPRINT } are provided to facilitate a very simple implementation, and as an example. * * \ingroup ITKCommon * */ template class ITK_TEMPLATE_EXPORT MetaDataObject : public MetaDataObjectBase { public: ITK_DISALLOW_COPY_AND_MOVE(MetaDataObject); /** Smart pointer type alias support */ using Self = MetaDataObject; using Superclass = MetaDataObjectBase; using Pointer = SmartPointer; using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(MetaDataObject); /** * The definition of this function is necessary to fulfill * the interface of the MetaDataObjectBase * \author Hans J. Johnson * \return A pointer to a const char array containing the unique type name. */ const char * GetMetaDataObjectTypeName() const override; /** * The definition of this function is necessary to fulfill * the interface of the MetaDataObjectBase * \author Hans J. Johnson * \return A constant reference to a std::type_info object */ const std::type_info & GetMetaDataObjectTypeInfo() const override; /** * Function to return the stored value of type MetaDataObjectType. * \author Hans J. Johnson * \return a constant reference to a MetaDataObjectType */ const MetaDataObjectType & GetMetaDataObjectValue() const; /** * Function to set the stored value of type MetaDataObjectType. * \author Hans J. Johnson * \param newValue A constant reference to at MetaDataObjectType. */ void SetMetaDataObjectValue(const MetaDataObjectType & newValue); /** * Defines the default behavior for printing out this element * \param os An output stream */ void Print(std::ostream & os) const override; /** Returns (metaDataObject1 == metaDataObject2). */ friend bool operator==(const Self & lhs, const Self & rhs) { return Self::EqualValues(lhs.m_MetaDataObjectValue, rhs.m_MetaDataObjectValue); } /** Returns (metaDataObject1 != metaDataObject2). */ friend bool operator!=(const Self & lhs, const Self & rhs) { return !(lhs == rhs); } protected: MetaDataObject() = default; ~MetaDataObject() override = default; private: /** Assigns the value of `source` to `target`. * \note The trailing return type is there, just to enable SFINAE.*/ template static auto Assign(TValue & target, const TValue & source) -> decltype(target = source) { return target = source; } /** `Assign` overload for C-style arrays (as well as arrays of arrays). */ template static void Assign(TValue (&target)[VNumberOfElements], const TValue (&source)[VNumberOfElements]) { for (size_t i = 0; i < VNumberOfElements; ++i) { Self::Assign(target[i], source[i]); } } /** Tells whether the specified arguments compare equal. * \note The trailing return type is there, just to enable SFINAE.*/ template static auto EqualValues(const TValue & lhs, const TValue & rhs) -> decltype(lhs == rhs) { return lhs == rhs; } /** `EqualValues` overload for C-style arrays (as well as arrays of arrays). */ template static bool EqualValues(const TValue (&lhs)[VNumberOfElements], const TValue (&rhs)[VNumberOfElements]) { for (size_t i = 0; i < VNumberOfElements; ++i) { if (!Self::EqualValues(lhs[i], rhs[i])) { return false; } } return true; } /** Internal helper function used to implement operator== for MetaDataObjectBase. */ bool Equal(const MetaDataObjectBase & metaDataObjectBase) const override { const auto metaDataObject = dynamic_cast(&metaDataObjectBase); return (metaDataObject != nullptr) && (*this == *metaDataObject); } /** * A variable to store this derived type. * \author Hans J. Johnson */ MetaDataObjectType m_MetaDataObjectValue{}; }; /** * EncapsulateMetaData is a convenience function that encapsulates raw MetaData into a * MetaDataObject that can be put into the MetaDataDictionary. * \param Dictionary reference to a dictionary * \param key string identifier for this object * \param invalue the value of type T that is to be encapsulated. */ template inline void EncapsulateMetaData(MetaDataDictionary & Dictionary, const std::string & key, const T & invalue) { typename MetaDataObject::Pointer temp = MetaDataObject::New(); temp->SetMetaDataObjectValue(invalue); Dictionary[key] = temp; } template inline void EncapsulateMetaData(MetaDataDictionary & Dictionary, const char * key, const T & invalue) { EncapsulateMetaData(Dictionary, std::string(key), invalue); } /** * ExposeMetaData provides a shortcut for pulling a value of type * T out of a MetaDataDictionary. * If Dictionary[key] isn't set, return false, otherwise copy into * outval reference and return true. * \param Dictionary -- reference to a dictionary * \param key -- string identifier for this object * \param outval -- where to store value found in table. */ template inline bool ExposeMetaData(const MetaDataDictionary & Dictionary, const std::string key, T & outval) { auto keyIter = Dictionary.Find(key); if (keyIter == Dictionary.End()) { return false; } auto const * const TempMetaDataObject = dynamic_cast const *>(keyIter->second.GetPointer()); if (TempMetaDataObject == nullptr) { return false; } outval = TempMetaDataObject->GetMetaDataObjectValue(); return true; } } // end namespace itk /** * \def ITK_NATIVE_TYPE_METADATAPRINT( TYPE_NAME ) * \brief An ugly macro to facilitate creating a simple implementation of * the MetaDataObject::Print() function for types that * have operator<< defined. * \param TYPE_NAME the native type parameter type */ #define ITK_NATIVE_TYPE_METADATAPRINT(TYPE_NAME) \ template <> \ void itk::MetaDataObject::Print(std::ostream & os) const \ { \ os << this->m_MetaDataObjectValue << std::endl; \ } /** * \def ITK_OBJECT_TYPE_METADATAPRINT_1COMMA( TYPE_NAME_PART1, TYPE_NAME_PART2 ) * \brief An ugly macro to facilitate creating a simple implementation of * the MetaDataObject< Type >::Print() function for * itk::Objects that have 1 comma in their type definition * \param TYPE_NAME_PART1 * \param TYPE_NAME_PART2 */ #define ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(TYPE_NAME_PART1, TYPE_NAME_PART2) \ template <> \ void itk::MetaDataObject::Print(std::ostream & os) const \ { \ this->m_MetaDataObjectValue->Print(os); \ } /** * \def ITK_IMAGE_TYPE_METADATAPRINT( STORAGE_TYPE ) * An ugly macro to facilitate creating a simple implementation of * the MetaDataObject::Print() function for * itk::Image\\::Pointer * \param STORAGE_TYPE The storage type of the image type to print. */ #define ITK_IMAGE_TYPE_METADATAPRINT(STORAGE_TYPE) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) #ifndef ITK_MANUAL_INSTANTIATION # include "itkMetaDataObject.hxx" #endif #endif // itkMetaDataObject_h /** Explicit instantiations */ #ifndef ITK_TEMPLATE_EXPLICIT_MetaDataObject // Explicit instantiation is required to ensure correct dynamic_cast // behavior across shared libraries. // // IMPORTANT: Since within the same compilation unit, // ITK_TEMPLATE_EXPLICIT_ defined and undefined states // need to be considered. This code *MUST* be *OUTSIDE* the header // guards. // #if defined(ITKCommon_EXPORTS) // We are building this library # define ITKCommon_EXPORT_EXPLICIT ITK_TEMPLATE_EXPORT #else // We are using this library # define ITKCommon_EXPORT_EXPLICIT ITKCommon_EXPORT #endif namespace itk { ITK_GCC_PRAGMA_DIAG_PUSH() ITK_GCC_PRAGMA_DIAG(ignored "-Wattributes") extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject>; ITK_GCC_PRAGMA_DIAG_POP() } // end namespace itk #undef ITKCommon_EXPORT_EXPLICIT #endif