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 #ifndef itkTreeNode_hxx
19 #define itkTreeNode_hxx
20 
21 #include "itkMacro.h"
22 #include "itkTreeNode.h"
23 #include <cstring>
24 
25 namespace itk
26 {
27 
28 /** Destructor */
29 template< typename TValue >
30 TreeNode< TValue >
~TreeNode()31 ::~TreeNode()
32 {
33   if ( m_Parent )
34     {
35     m_Parent->Remove(this);
36     }
37 
38   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
39 
40   for ( ChildIdentifier i = numberOfChildren; i > 0; i-- )
41     {
42     m_Children[i - 1]->SetParent(nullptr);
43     }
44   m_Children.clear();
45   m_Parent = nullptr;
46   m_Data = 0;
47 }
48 
49 /** Return the parent node */
50 template< typename TValue >
51 TreeNode< TValue > *
52 TreeNode< TValue >
GetParent() const53 ::GetParent() const
54 {
55   return m_Parent;
56 }
57 
58 /** Get a child */
59 template< typename TValue >
60 TreeNode< TValue > *
61 TreeNode< TValue >
GetChild(ChildIdentifier number) const62 ::GetChild(ChildIdentifier number) const
63 {
64   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
65 
66   if ( number < numberOfChildren )
67     {
68     return m_Children[number];
69     }
70   else
71     {
72     return nullptr;
73     }
74 }
75 
76 /** Set the value of a node */
77 template< typename TValue >
78 TValue
79 TreeNode< TValue >
Set(const TValue data)80 ::Set(const TValue data)
81 {
82   TValue help = m_Data;
83 
84   m_Data = data;
85   return help;
86 }
87 
88 /** Get the data of node */
89 template< typename TValue >
90 const TValue &
91 TreeNode< TValue >
Get() const92 ::Get() const
93 {
94   return m_Data;
95 }
96 
97 /** Return true if has a parent */
98 template< typename TValue >
99 bool
100 TreeNode< TValue >
HasParent() const101 ::HasParent() const
102 {
103   return ( m_Parent ) ? true : false;
104 }
105 
106 /** Set the parent node */
107 template< typename TValue >
108 void
109 TreeNode< TValue >
SetParent(TreeNode<TValue> * node)110 ::SetParent(TreeNode< TValue > *node)
111 {
112   //keep ourself alive just a bit longer
113   Pointer ourself = this;
114 
115   if ( m_Parent != nullptr )
116     {
117     m_Parent->Remove(this);
118     }
119   m_Parent = node;
120 }
121 
122 /** Return true if the node has children */
123 template< typename TValue >
124 bool
125 TreeNode< TValue >
HasChildren() const126 ::HasChildren() const
127 {
128   return ( !m_Children.empty() ) ? true : false;
129 }
130 
131 /** Return the number of children */
132 template< typename TValue >
133 typename TreeNode< TValue >::ChildIdentifier
134 TreeNode< TValue >
CountChildren() const135 ::CountChildren() const
136 {
137   return static_cast< ChildIdentifier >( m_Children.size() );
138 }
139 
140 /** Remove a child node from the current node */
141 template< typename TValue >
142 bool
143 TreeNode< TValue >
Remove(Self * n)144 ::Remove(Self *n)
145 {
146   typename std::vector< Pointer >::iterator pos;
147   pos = std::find(m_Children.begin(), m_Children.end(), n);
148   if ( pos != m_Children.end() )
149     {
150     //keep node alive just a bit longer
151     Pointer position = n;
152     m_Children.erase(pos);
153     n->SetParent(nullptr);
154     return true;
155     }
156   return false;
157 }
158 
159 /** Replace a child by a new one */
160 template< typename TValue >
161 bool
162 TreeNode< TValue >
ReplaceChild(Self * oldChild,Self * newChild)163 ::ReplaceChild(Self *oldChild, Self *newChild)
164 {
165   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
166 
167   for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
168     {
169     if ( m_Children[i] == oldChild )
170       {
171       m_Children[i] = newChild;
172       return true;
173       }
174     }
175   return false;
176 }
177 
178 /** Return the child position given a node */
179 template< typename TValue >
180 OffsetValueType
181 TreeNode< TValue >
ChildPosition(const Self * node) const182 ::ChildPosition(const Self *node) const
183 {
184   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
185 
186   for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
187     {
188     if ( m_Children[i] == node )
189       {
190       return i;
191       }
192     }
193   return -1;
194 }
195 
196 /** Return the child position given an element, the first child found. */
197 template< typename TValue >
198 typename TreeNode< TValue >::ChildIdentifier
199 TreeNode< TValue >
ChildPosition(TValue element) const200 ::ChildPosition(TValue element) const
201 {
202   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
203 
204   for ( ChildIdentifier i = 0; i < numberOfChildren; i++ )
205     {
206     if ( m_Children[i]->Get() == element )
207       {
208       return i;
209       }
210     }
211   return -1;
212 }
213 
214 /** Add a child node */
215 template< typename TValue >
216 void
217 TreeNode< TValue >
AddChild(Self * node)218 ::AddChild(Self *node)
219 {
220   Pointer nodeKeepAlive = node;
221 
222   node->SetParent(this);
223   m_Children.push_back(node);
224 }
225 
226 /** Add a child at a specific position in the children list */
227 template< typename TValue >
228 void
229 TreeNode< TValue >
AddChild(ChildIdentifier number,Self * node)230 ::AddChild(ChildIdentifier number, Self *node)
231 {
232   const auto numberOfChildren = static_cast< ChildIdentifier >( m_Children.size() );
233   auto childId = static_cast<ChildIdentifier>( number );
234 
235   if ( childId > numberOfChildren )
236     {
237     m_Children.resize(childId);
238     for ( ChildIdentifier i = numberOfChildren; i <= childId; i++ )
239       {
240       m_Children[i] = nullptr;
241       }
242     m_Children[number] = node;
243     return;
244     }
245 
246   m_Children[number] = node;
247 }
248 
249 /** Get the number of children given a name and a depth */
250 template< typename TValue >
251 typename TreeNode< TValue >::ChildIdentifier
252 TreeNode< TValue >
GetNumberOfChildren(unsigned int depth,char * name) const253 ::GetNumberOfChildren(unsigned int depth, char *name) const
254 {
255   auto it = m_Children.begin();
256   auto itEnd = m_Children.end();
257 
258   ChildIdentifier cnt = 0;
259   while ( it != itEnd )
260     {
261     if ( name == nullptr || strstr(typeid( **it ).name(), name) )
262       {
263       ++cnt;
264       }
265     ++it;
266     }
267 
268   it = m_Children.begin();
269   itEnd = m_Children.end();
270   if ( depth > 0 )
271     {
272     while ( it != itEnd )
273       {
274       cnt += ( *it )->GetNumberOfChildren(depth - 1, name);
275       ++it;
276       }
277     }
278 
279   return cnt;
280 }
281 
282 /** Get children given a name and a depth */
283 #if !defined( ITK_WRAPPING_PARSER )
284 template< typename TValue >
285 typename TreeNode< TValue >::ChildrenListType *
286 TreeNode< TValue >
GetChildren(unsigned int depth,char * name) const287 ::GetChildren(unsigned int depth, char *name) const
288 {
289   auto * children = new ChildrenListType;
290 
291   auto childrenListIt = m_Children.begin();
292   auto childrenListEnd = m_Children.end();
293 
294   while ( childrenListIt != childrenListEnd )
295     {
296     if ( name == nullptr || strstr(typeid( **childrenListIt ).name(), name) )
297       {
298       children->push_back(*childrenListIt);
299       }
300     if ( depth > 0 )
301       {
302       ChildrenListType *nextchildren = ( **childrenListIt ).GetChildren(depth - 1,
303                                                                         name);
304       // Add the child to the current list
305       typename ChildrenListType::const_iterator nextIt = nextchildren->begin();
306       while ( nextIt != nextchildren->end() )
307         {
308         children->push_back(*nextIt);
309         ++nextIt;
310         }
311       delete nextchildren;
312       }
313     ++childrenListIt;
314     }
315 
316   return children;
317 }
318 
319 #endif
320 } // namespace itk
321 
322 #endif
323