1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 /*=========================================================================
19  *
20  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  *  For complete copyright, license and disclaimer of warranty information
25  *  please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 #ifndef itkMetaDataObject_h
29 #define itkMetaDataObject_h
30 
31 #include "itkMetaDataDictionary.h"
32 #include "itkMacro.h"
33 #include "itkArray.h"
34 #include "itkMatrix.h"
35 
36 #include <cstring>
37 
38 namespace itk
39 {
40 /**
41  * \class MetaDataObject
42  * \brief Allows arbitrary data types to be stored as MetaDataObjectBase types,
43  *        and to be stored in a MetaDataDictionary.
44  *
45  * \author Hans J. Johnson
46  *
47  * The MetaDataObject class is a templated class that
48  * is a specialization of the MetaDataObjectBase type.
49  * This class allows arbitrary data types to be
50  * stored as MetaDataObjectBase types, and to be stored in
51  * a MetaDataDictionary.
52  *
53  * Any class or built in type that has valid copy constructor and operator=
54  * can be wrapped directly with this simple template type.
55  *
56  * Classes or built in types that do not have valid copy constructors or operator=
57  * implemented will have to implement those functions by deriving from MetaDataObject<MetaDataObjectType>
58  * and redefining the copy constructor and initializing constructor and the Get/Set functions
59  * to work around those deficiencies.
60  *
61  * The behavior of the MetaDataObject<Type>::Print() function has many plausible
62  * application dependent implementations.  The default implementation prints the
63  * string "[UNKNOWN PRINT CHARACTERISTICS]" that works for all possible
64  * MetaDataObject types.
65  *
66  * The application developer may overload the default implementation to provide
67  * a specialized Print() characteristics to produce results desirable for their application.
68  * A set of very crude Macros {NATIVE_TYPE_METADATAPRINT, ITK_OBJECT_TYPE_METADATAPRINT_1COMMA, ITK_IMAGE_TYPE_METADATAPRINT  }
69  * are provided to facilitate a very simple implementation, and as an example.
70  * \ingroup ITKCommon
71  */
72 template< typename MetaDataObjectType >
73 class ITK_TEMPLATE_EXPORT MetaDataObject:public MetaDataObjectBase
74 {
75 public:
76   ITK_DISALLOW_COPY_AND_ASSIGN(MetaDataObject);
77 
78   /** Smart pointer type alias support */
79   using Self = MetaDataObject;
80   using Superclass = MetaDataObjectBase;
81   using Pointer = SmartPointer< Self >;
82   using ConstPointer = SmartPointer< const Self >;
83 
84   /** Method for creation through the object factory. */
85   itkFactorylessNewMacro(Self);
86 
87   /** Run-time type information (and related methods). */
88   itkTypeMacro(MetaDataObject, MetaDataObjectBase);
89 
90   /**
91    * The definition of this function is necessary to fulfill
92    * the interface of the MetaDataObjectBase
93    * \author Hans J. Johnson
94    * \return A pointer to a const char array containing the unique type name.
95    */
96   const char * GetMetaDataObjectTypeName() const override;
97 
98   /**
99    * The definition of this function is necessary to fulfill
100    * the interface of the MetaDataObjectBase
101    * \author Hans J. Johnson
102    * \return A constant reference to a std::type_info object
103    */
104   const std::type_info & GetMetaDataObjectTypeInfo() const override;
105 
106   /**
107    * Function to return the stored value of type MetaDataObjectType.
108    * \author Hans J. Johnson
109    * \return a constant reference to a MetaDataObjectType
110    */
111   const MetaDataObjectType & GetMetaDataObjectValue() const;
112 
113   /**
114    * Function to set the stored value of type MetaDataObjectType.
115    * \author Hans J. Johnson
116    * \param newValue A constant reference to at MetaDataObjectType.
117    */
118   void SetMetaDataObjectValue(const MetaDataObjectType & newValue);
119 
120   /**
121    * Defines the default behavior for printing out this element
122    * \param os An output stream
123    */
124   void Print(std::ostream & os) const override;
125 
126 protected:
127   MetaDataObject() = default;
128   ~MetaDataObject() override = default;
129 
130 private:
131   /**
132    * A variable to store this derived type.
133    * \author Hans J. Johnson
134    */
135   MetaDataObjectType m_MetaDataObjectValue;
136 };
137 
138 /**
139  * EncapsulateMetaData is a convenience function that encapsulates raw MetaData into a
140  * MetaDataObject that can be put into the MetaDataDictionary.
141  * \param Dictionary TODO
142  * \param key TODO
143  * \param invalue the value of type T that is to be encapsulated.
144  * \return A smartpointer ot a MetaDataObject that is suitable for
145  * insertion into a MetaDataDictionary.
146  */
147 template< typename T >
EncapsulateMetaData(MetaDataDictionary & Dictionary,const std::string & key,const T & invalue)148 inline void EncapsulateMetaData(MetaDataDictionary & Dictionary, const std::string & key, const T & invalue)
149 {
150   typename MetaDataObject< T >::Pointer temp = MetaDataObject< T >::New();
151   temp->SetMetaDataObjectValue(invalue);
152   Dictionary[key] = temp;
153 }
154 
155 template< typename T >
EncapsulateMetaData(MetaDataDictionary & Dictionary,const char * key,const T & invalue)156 inline void EncapsulateMetaData(MetaDataDictionary & Dictionary, const char *key, const T & invalue)
157 {
158   EncapsulateMetaData(Dictionary, std::string(key), invalue);
159 }
160 
161 /**
162  * ExposeMetaData provides a shortcut for pulling a value of type
163  * T out of a MetaDataDictionary.
164  * If Dictionary[key] isn't set, return false, otherwise copy into
165  * outval reference and return true.
166  * \param Dictionary -- reference to a dictionary
167  * \param key -- string identifier for this object
168  * \param outval -- where to store value found in table.
169  */
170 template< typename T >
ExposeMetaData(const MetaDataDictionary & Dictionary,const std::string key,T & outval)171 inline bool ExposeMetaData(const MetaDataDictionary & Dictionary, const std::string key, T & outval)
172 {
173   auto keyIter = Dictionary.Find(key);
174   if ( keyIter == Dictionary.End() )
175     {
176     return false;
177     }
178 
179   auto const * const TempMetaDataObject = dynamic_cast< MetaDataObject< T > const * >( keyIter->second.GetPointer() );
180   if ( TempMetaDataObject == nullptr )
181     {
182     return false;
183     }
184 
185   outval = TempMetaDataObject->GetMetaDataObjectValue();
186   return true;
187 }
188 
189 } // end namespace itk
190 
191 /**
192  * \def ITK_NATIVE_TYPE_METADATAPRINT( TYPE_NAME )
193  * \brief An ugly macro to facilitate creating a simple implementation of
194  * the MetaDataObject<Type>::Print() function for types that
195  * have operator<< defined.
196  * \param TYPE_NAME the native type parameter type
197  */
198 #define ITK_NATIVE_TYPE_METADATAPRINT(TYPE_NAME)        \
199   template< >                                       \
200   void                                              \
201   ::itk::MetaDataObject< TYPE_NAME >                  \
202   ::Print(std::ostream & os) const                  \
203     {                                               \
204     os << this->m_MetaDataObjectValue << std::endl; \
205     }                                               \
206 
207 /**
208  * \def ITK_OBJECT_TYPE_METADATAPRINT_1COMMA( TYPE_NAME_PART1, TYPE_NAME_PART2 )
209  * \brief An ugly macro to facilitate creating a simple implementation of
210  * the MetaDataObject< Type >::Print() function for
211  * itk::Objects that have 1 comma in their type definition
212  * \param TYPE_NAME_PART1
213  * \param TYPE_NAME_PART2
214  */
215 #define ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(TYPE_NAME_PART1, TYPE_NAME_PART2) \
216   template< >                                                                  \
217   void                                                                         \
218   itk::MetaDataObject< TYPE_NAME_PART1, TYPE_NAME_PART2 >                      \
219   ::Print(std::ostream & os) const                                             \
220     {                                                                          \
221     this->m_MetaDataObjectValue->Print(os);                                    \
222     }                                                                          \
223 
224 /**
225  * \def ITK_IMAGE_TYPE_METADATAPRINT( STORAGE_TYPE )
226  * An ugly macro to facilitate creating a simple implementation of
227  * the MetaDataObject<Type>::Print() function for
228  * itk::Image\<STORAGE_TYPE,[1-8]\>\::Pointer
229  * \param STORAGE_TYPE The storage type of the image type to print.
230  */
231 #define ITK_IMAGE_TYPE_METADATAPRINT(STORAGE_TYPE)                             \
232   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 1 >::Pointer) \
233   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 2 >::Pointer) \
234   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 3 >::Pointer) \
235   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 4 >::Pointer) \
236   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 5 >::Pointer) \
237   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 6 >::Pointer) \
238   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 7 >::Pointer) \
239   ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image< STORAGE_TYPE, 8 >::Pointer) \
240 
241 #ifndef ITK_MANUAL_INSTANTIATION
242 #include "itkMetaDataObject.hxx"
243 #endif
244 
245 #endif //itkMetaDataObject_h
246 
247 /** Explicit instantiations */
248 #ifndef ITK_TEMPLATE_EXPLICIT_MetaDataObject
249 // Explicit instantiation is required to ensure correct dynamic_cast
250 // behavior across shared libraries.
251 //
252 // IMPORTANT: Since within the same compilation unit,
253 //            ITK_TEMPLATE_EXPLICIT_<classname> defined and undefined states
254 //            need to be considered. This code *MUST* be *OUTSIDE* the header
255 //            guards.
256 //
257 #  if defined( ITKCommon_EXPORTS )
258 //   We are building this library
259 #    define ITKCommon_EXPORT_EXPLICIT ITK_TEMPLATE_EXPORT
260 #  else
261 //   We are using this library
262 #    define ITKCommon_EXPORT_EXPLICIT ITKCommon_EXPORT
263 #  endif
264 namespace itk
265 {
266 
267 ITK_GCC_PRAGMA_DIAG_PUSH()
268 ITK_GCC_PRAGMA_DIAG(ignored "-Wattributes")
269 
270 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< bool >;
271 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned char >;
272 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< char >;
273 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< signed char >;
274 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned short >;
275 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< short >;
276 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned int >;
277 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< int >;
278 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned long >;
279 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< long >;
280 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned long long >;
281 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< long long >;
282 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< float >;
283 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< double >;
284 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::string >;
285 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::vector<float> >;
286 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::vector<double> >;
287 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::vector<std::vector<float> > >;
288 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::vector<std::vector<double> > >;
289 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<char> >;
290 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<int> >;
291 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<float> >;
292 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<double> >;
293 extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Matrix<double> >;
294 
295 ITK_GCC_PRAGMA_DIAG_POP()
296 
297 } // end namespace itk
298 #  undef ITKCommon_EXPORT_EXPLICIT
299 #endif
300