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 #include <iostream>
20 #include "itkAffineTransform.h"
21 #include "itkSimpleDataObjectDecorator.h"
22 #include "itkDataObjectDecorator.h"
23 #include "itkAutoPointerDataObjectDecorator.h"
24 #include "itkTestingMacros.h"
25 
26 namespace {
27 template <typename CharType, typename TraitsType, typename MemberType, typename AllocatorType>
28 std::basic_ostream<CharType, TraitsType>&
operator <<(std::basic_ostream<CharType,TraitsType> & os,const std::vector<MemberType,AllocatorType> & p)29 operator<<(std::basic_ostream<CharType, TraitsType>&os, const std::vector<MemberType,AllocatorType> &p)
30 {
31   os << "vector<" << typeid(MemberType).name() << "> with " << p.size() << " elements " << std::endl;
32   return os;
33 }
34 }
35 
itkDecoratorTest(int,char * [])36 int itkDecoratorTest(int, char* [] )
37 {
38   int status = 0;
39 
40   std::cout << "----------------------------------------------------"
41             << std::endl;
42 
43   using FloatObjectType = itk::SimpleDataObjectDecorator<float>;
44 
45   FloatObjectType::Pointer f = FloatObjectType::New();
46   f->Set(5.0);
47 
48   std::cout << "Value of f: " << f->Get() << std::endl;
49   std::cout << "FloatDataObject: " << f << std::endl;
50 
51   std::cout << "----------------------------------------------------"
52             << std::endl;
53 
54   using TransformType = itk::AffineTransform<double, 3>;
55   using TransformObjectType = itk::DataObjectDecorator<TransformType>;
56 
57   TransformObjectType::Pointer decoratedTransform = TransformObjectType::New();
58   TransformType::Pointer transformObject = TransformType::New();
59   const TransformType * constTransformObject = transformObject;
60 
61   transformObject->Scale( 5.0 );
62 
63   decoratedTransform->Set( constTransformObject );
64 
65   const itk::ModifiedTimeType t1 = decoratedTransform->GetMTime();
66   transformObject->Modified();
67   TEST_EXPECT_TRUE(t1 < decoratedTransform->GetMTime());
68 
69   TransformObjectType::Pointer decoratedTransform2 = TransformObjectType::New();
70   decoratedTransform2->Graft( decoratedTransform );
71 
72   TEST_EXPECT_EQUAL( decoratedTransform2->Get(), decoratedTransform->Get() );
73 
74   const itk::ModifiedTimeType t2 = decoratedTransform->GetMTime();
75   decoratedTransform2->GetModifiable()->Modified();
76   TEST_EXPECT_TRUE(t2 < decoratedTransform->GetMTime());
77 
78 
79   std::cout << "Value of decoratedTransform: ";
80   decoratedTransform->Get()->Print(std::cout);
81   std::cout << "TransformDataObject: " << decoratedTransform;
82 
83   using TransformBaseType = itk::Transform<double, 3>;
84   using TransformBaseObjectType = itk::DataObjectDecorator<TransformBaseType>;
85 
86   TransformBaseObjectType::Pointer decoratedBaseTransform = TransformBaseObjectType::New();
87   //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
88   decoratedBaseTransform->Graft( decoratedTransform.GetPointer() );
89   TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
90 
91   decoratedBaseTransform->ReleaseData();
92   TEST_EXPECT_TRUE( decoratedBaseTransform->Get() == nullptr );
93   //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
94   decoratedBaseTransform->Graft( f.GetPointer() );
95   TEST_EXPECT_TRUE( decoratedBaseTransform->Get() == nullptr );
96 
97   decoratedBaseTransform->Graft( static_cast<itk::DataObject *>(nullptr) );
98   //NOTE: GetPointer is needed to force selection of the correct overloaded function signature.
99   decoratedBaseTransform->Graft( decoratedTransform.GetPointer() );
100   TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
101 
102   decoratedBaseTransform->Graft( static_cast<itk::DataObject *>(nullptr) );
103   TEST_EXPECT_TRUE( decoratedBaseTransform->Get() != nullptr );
104 
105   decoratedTransform->ReleaseData();
106   decoratedTransform->Graft( decoratedBaseTransform );
107   TEST_EXPECT_TRUE( decoratedTransform->Get() == nullptr );
108 
109   std::cout << "----------------------------------------------------"
110             << std::endl;
111 
112   using VectorType = std::vector<float>;
113   using VectorPointer = VectorType*;
114   using VectorObjectType = itk::SimpleDataObjectDecorator<VectorType>;
115   using VectorPointerObjectType = itk::AutoPointerDataObjectDecorator<VectorType>;
116 
117   VectorType v;
118   v.resize(5);
119   std::cout << v << std::endl;
120   VectorObjectType::Pointer vo = VectorObjectType::New();
121   vo->Set(v);
122   std::cout << vo;
123   std::cout << "----------------------------------------------------"
124             << std::endl;
125 
126   // The following code block will NOT cause a memory leak because the
127   // ownership of the dynamically allocated memory is passed to the
128   // AutoPointerDataObjectDecorator
129   {
130   VectorPointer vp;
131   vp = new VectorType;
132   vp->resize(3);
133   std::cout << *vp << std::endl;
134 
135   VectorPointerObjectType::Pointer vop = VectorPointerObjectType::New();
136   vop->Set(vp);
137 
138   std::cout << vop;
139   }
140 
141   std::cout << "----------------------------------------------------"
142             << std::endl;
143 
144   // The following code block will cause a memory leak because the
145   // decorator does not deallocate the memory that was passed in on a
146   // pointer. The AutoPointerDataObjectDecorator does delete the memory.
147   //using VectorPointerObjectType2 = itk::SimpleDataObjectDecorator<VectorPointer>;
148   //{
149   //VectorPointer vp2;
150   //vp2 = new VectorType;
151   //vp2->resize(4);
152   //std::cout << *vp2 << std::endl;
153 
154   //VectorPointerObjectType2::Pointer vop2 = VectorPointerObjectType2::New();
155   //vop2->Set(vp2);
156 
157   //std::cout << vop2;
158   //}
159 
160   return status;
161 }
162