00001 /*========================================================================= 00002 00003 Program: Medical Imaging & Interaction Toolkit 00004 Language: C++ 00005 Date: $Date$ 00006 Version: $Revision$ 00007 00008 Copyright (c) German Cancer Research Center, Division of Medical and 00009 Biological Informatics. All rights reserved. 00010 See MITKCopyright.txt or https://www.mitk.org/copyright.html for details. 00011 00012 This software is distributed WITHOUT ANY WARRANTY; without even 00013 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00014 PURPOSE. See the above copyright notices for more information. 00015 00016 =========================================================================*/ 00017 00018 00019 #ifndef MITKDATASTORAGE_H_HEADER_INCLUDED_ 00020 #define MITKDATASTORAGE_H_HEADER_INCLUDED_ 00021 00022 #include "itkObject.h" 00023 #include "mitkCommon.h" 00024 #include "mitkMessage.h" 00025 #include "itkVectorContainer.h" 00026 #include "mitkDataNode.h" 00027 #include "mitkGeometry3D.h" 00028 #include "itkSimpleFastMutexLock.h" 00029 #include <map> 00030 00031 namespace mitk { 00032 00033 class NodePredicateBase; 00034 class DataNode; 00035 class BaseRenderer; 00036 00037 //##Documentation 00038 //## @brief Data management class that handles 'was created by' relations 00039 //## 00040 //## The DataStorage provides data storage and management functionality. 00041 //## It handles a 'was created by' relation by associating each data object with a 00042 //## set of source objects, that this object was created from. 00043 //## Thus, nodes are stored in a noncyclical directed graph data structure. 00044 //## If a new node is added to the DataStorage, AddNodeEvent is emitted. 00045 //## If a node is removed, RemoveNodeEvent is emitted. 00046 //## 00047 //## 00048 //## \ingroup DataStorage 00049 class MITK_CORE_EXPORT DataStorage : public itk::Object 00050 { 00051 public: 00052 mitkClassMacro(DataStorage, itk::Object); 00053 00054 //##Documentation 00055 //## @brief A Container of objects that is used as a result set of GetSubset() query operations (Set of SmartPointers to DataNodes). 00056 typedef itk::VectorContainer<unsigned int, mitk::DataNode::Pointer> SetOfObjects; 00057 00058 //##Documentation 00059 //## @brief Adds a DataNode containing a data object to its internal storage 00060 //## 00061 //## This Method adds a new data object to the DataStorage. The new object is 00062 //## passed in the first parameter. The second parameter is a set 00063 //## of source objects, that were used to create this object. The new object will have 00064 //## a 'was created from' relation to its source objects. 00065 //## the addition of a new object will fire the notification mechanism. 00066 //## If the node parameter is NULL or if the DataNode has already been added, 00067 //## an exception will be thrown. 00068 virtual void Add(mitk::DataNode* node, const mitk::DataStorage::SetOfObjects* parents = NULL) = 0; 00069 00070 //##Documentation 00071 //## @brief Convenience method to add a node that has one parent 00072 //## 00073 void Add(mitk::DataNode* node, mitk::DataNode* parent); 00074 00075 //##Documentation 00076 //## @brief Removes node from the DataStorage 00077 //## 00078 virtual void Remove(const mitk::DataNode* node) = 0; 00079 00080 //##Documentation 00081 //## @brief Checks if a node exists in the DataStorage 00082 //## 00083 virtual bool Exists(const mitk::DataNode* node) const = 0; 00084 00085 //##Documentation 00086 //## @brief Removes a set of nodes from the DataStorage 00087 //## 00088 void Remove(const mitk::DataStorage::SetOfObjects* nodes); 00089 00090 //##Documentation 00091 //## @brief returns a set of data objects that meet the given condition(s) 00092 //## 00093 //## GetSubset returns a set of objects with a specific data type that meet the condition(s) 00094 //## specified in the condition parameter. Conditions can be 00095 //## - data type of the data object 00096 //## - is source object of specific object (e.g. all source objects of node x) 00097 //## - has property with specific value (e.g. OrganType is Liver) 00098 //## - negation of any condition 00099 //## - conjunction of a set of conditions 00100 //## - disjunction of a set of conditions 00101 //## Conditions are implemented as predicates using the Composite Design Pattern 00102 //## (see definition of NodePredicateBase for details). 00103 //## The method returns a set of SmartPointers to the DataNodes that fulfill the 00104 //## conditions. A set of all objects can be retrieved with the GetAll() method; 00105 SetOfObjects::ConstPointer GetSubset(const NodePredicateBase* condition) const; 00106 00107 //##Documentation 00108 //## @brief returns a set of source objects for a given node that meet the given condition(s). 00109 //## 00110 virtual SetOfObjects::ConstPointer GetSources(const mitk::DataNode* node, const NodePredicateBase* condition = NULL, bool onlyDirectSources = true) const = 0; 00111 00112 //##Documentation 00113 //## @brief returns a set of derived objects for a given node. 00114 //## 00115 //## GetDerivations() returns a set of objects that are derived from the DataNode node. 00116 //## This means, that node was used to create the returned objects. If the parameter 00117 //## onlyDirectDerivations is set to true (default value), only objects that directly have 00118 //## node as one of their source objects will be returned. Otherwise, objects that are 00119 //## derived from derivations of node are returned too. 00120 //## The derived objects can be filtered with a predicate object as described in the GetSubset() 00121 //## method by providing a predicate as the condition parameter. 00122 virtual SetOfObjects::ConstPointer GetDerivations(const mitk::DataNode* node, const NodePredicateBase* condition = NULL, bool onlyDirectDerivations = true) const = 0; 00123 00124 //##Documentation 00125 //## @brief returns a set of all data objects that are stored in the data storage 00126 //## 00127 virtual SetOfObjects::ConstPointer GetAll() const = 0; 00128 00129 //##Documentation 00130 //## @brief Convenience method to get the first node that matches the predicate condition 00131 //## 00132 mitk::DataNode* GetNode(const NodePredicateBase* condition = NULL) const; 00133 00134 00135 //##Documentation 00136 //## @brief Convenience method to get the first node with a given name 00137 //## 00138 mitk::DataNode* GetNamedNode(const char* name) const; 00139 00140 //##Documentation 00141 //## @brief Convenience method to get the first node with a given name 00142 //## 00143 mitk::DataNode* GetNamedNode(const std::string name) const 00144 { 00145 return this->GetNamedNode(name.c_str()); 00146 } 00147 00148 //##Documentation 00149 //## @brief Convenience method to get the first node with a given name that is derived from sourceNode 00150 //## 00151 mitk::DataNode* GetNamedDerivedNode(const char* name, const mitk::DataNode* sourceNode, bool onlyDirectDerivations = true) const; 00152 00153 //##Documentation 00154 //## @brief Convenience method to get the first data object of a given data type with a given name 00155 //## 00156 template <class DataType> 00157 DataType* GetNamedObject(const char* name) const 00158 { 00159 if (name == NULL) 00160 return NULL; 00161 mitk::DataNode* n = this->GetNamedNode(name); 00162 if (n == NULL) 00163 return NULL; 00164 else 00165 return dynamic_cast<DataType*>(n->GetData()); 00166 } 00167 //##Documentation 00168 //## @brief Convenience method to get the first data object of a given data type with a given name 00169 //## 00170 template <class DataType> 00171 DataType* GetNamedObject(const std::string name) const 00172 { 00173 return this->GetNamedObject<DataType>(name.c_str()); 00174 } 00175 00176 //##Documentation 00177 //## @brief Convenience method to get the first data object of a given data type with a given name that is derived from a specific node 00178 //## 00179 template <class DataType> 00180 DataType* GetNamedDerivedObject(const char* name, const mitk::DataNode* sourceNode, bool onlyDirectDerivations = true) const 00181 { 00182 if (name == NULL) 00183 return NULL; 00184 mitk::DataNode* n = this->GetNamedDerivedNode(name, sourceNode, onlyDirectDerivations); 00185 if (n == NULL) 00186 return NULL; 00187 else 00188 return dynamic_cast<DataType*>(n->GetData()); 00189 } 00190 00191 //##Documentation 00192 //## @brief Returns a list of used grouptags 00193 //## 00194 const DataNode::GroupTagList GetGroupTags() const; 00195 00196 /*ITK Mutex */ 00197 mutable itk::SimpleFastMutexLock m_MutexOne; 00198 00199 /* Public Events */ 00200 typedef Message1<const mitk::DataNode*> DataStorageEvent; 00201 //##Documentation 00202 //## @brief AddEvent is emitted whenever a new node has been added to the DataStorage. 00203 //## 00204 //## Observers should register to this event by calling myDataStorage->AddNodeEvent.AddListener(myObject, MyObject::MyMethod). 00205 //## After registering, myObject->MyMethod() will be called every time a new node has been added to the DataStorage. 00206 //## Observers should unregister by calling myDataStorage->AddNodeEvent.RemoveListener(myObject, MyObject::MyMethod). 00207 //## Note: AddEvents are _not_ emitted if a node is added to DataStorage by adding it to the the underlying DataTree! 00208 00209 // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef for 00210 // a Message1 object which is thread safe 00211 DataStorageEvent AddNodeEvent; 00212 00213 //##Documentation 00214 //## @brief RemoveEvent is emitted directly before a node is removed from the DataStorage. 00215 //## 00216 //## Observers should register to this event by calling myDataStorage->RemoveNodeEvent.AddListener(myObject, MyObject::MyMethod). 00217 //## After registering, myObject->MyMethod() will be called every time a new node has been added to the DataStorage. 00218 //## Observers should unregister by calling myDataStorage->RemoveNodeEvent.RemoveListener(myObject, MyObject::MyMethod). 00219 //## Note: RemoveEvents are also emitted if a node was removed from the DataStorage by deleting it from the underlying DataTree 00220 00221 // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef for 00222 // a Message1 object which is thread safe 00223 DataStorageEvent RemoveNodeEvent; 00224 00225 //##Documentation 00226 //## @brief ChangedEvent is emitted directly after a node was changed. 00227 //## 00228 //## Observers should register to this event by calling myDataStorage->ChangedNodeEvent.AddListener(myObject, MyObject::MyMethod). 00229 //## After registering, myObject->MyMethod() will be called every time a new node has been changed. 00230 //## Observers should unregister by calling myDataStorage->ChangedNodeEvent.RemoveListener(myObject, MyObject::MyMethod). 00231 //## Internally the DataStorage listens to itk::ModifiedEvents on the nodes and forwards them 00232 //## to the listeners of this event. 00233 00234 // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef for 00235 // a Message1 object which is thread safe 00236 DataStorageEvent ChangedNodeEvent; 00237 00238 //##Documentation 00239 //## @brief DeleteNodeEvent is emitted directly before a node is deleted. 00240 //## 00241 //## Observers should register to this event by calling myDataStorage->DeleteNodeEvent.AddListener(myObject, MyObject::MyMethod). 00242 //## After registering, myObject->MyMethod() will be called when a node is deleted. 00243 //## Observers should unregister by calling myDataStorage->DeleteNodeEvent.RemoveListener(myObject, MyObject::MyMethod). 00244 //## Internally the DataStorage listens to itk::DeleteEvents on the nodes and forwards them 00245 //## to the listeners of this event. 00246 00247 // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef for 00248 // a Message1 object which is thread safe 00249 DataStorageEvent DeleteNodeEvent; 00250 00251 //##Documentation 00252 //## @brief Compute the axis-parallel bounding geometry of the input objects 00253 //## 00254 //## Throws std::invalid_argument exception if input is NULL 00255 //## @param input set of objects of the DataStorage to be included in the bounding geometry 00256 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00257 //## and is set to @a false, the node is ignored for the bounding-box calculation. 00258 //## @param renderer see @a boolPropertyKey 00259 //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey 00260 mitk::TimeSlicedGeometry::Pointer ComputeBoundingGeometry3D( const SetOfObjects* input, const char* boolPropertyKey = NULL, mitk::BaseRenderer* renderer = NULL, const char* boolPropertyKey2 = NULL); 00261 00262 //##Documentation 00263 //## @brief Compute the axis-parallel bounding geometry of the data tree 00264 //## (bounding box, minimal spacing of the considered nodes, live-span) 00265 //## 00266 //## it -> an iterator to a data tree structure 00267 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00268 //## and is set to @a false, the node is ignored for the bounding-box calculation. 00269 //## @param renderer see @a boolPropertyKey 00270 //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey 00271 mitk::TimeSlicedGeometry::Pointer ComputeBoundingGeometry3D( const char* boolPropertyKey = NULL, mitk::BaseRenderer* renderer = NULL, const char* boolPropertyKey2 = NULL); 00272 00273 //##Documentation 00274 //## @brief Compute the axis-parallel bounding geometry of all visible parts of the 00275 //## data tree bounding box, minimal spacing of the considered nodes, live-span) 00276 //## 00277 //## Simply calls ComputeBoundingGeometry3D(it, "visible", renderer, boolPropertyKey). 00278 //## it -> an iterator of a data tree structure 00279 //## @param renderer the reference to the renderer 00280 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00281 //## and is set to @a false, the node is ignored for the bounding-box calculation. 00282 mitk::TimeSlicedGeometry::Pointer ComputeVisibleBoundingGeometry3D( mitk::BaseRenderer* renderer = NULL, const char* boolPropertyKey = NULL); 00283 00284 //##Documentation 00285 //## @brief Compute the bounding box of data tree structure 00286 //## it -> an iterator to a data tree structure 00287 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00288 //## and is set to @a false, the node is ignored for the bounding-box calculation. 00289 //## @param renderer see @a boolPropertyKey 00290 //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey 00291 mitk::BoundingBox::Pointer ComputeBoundingBox( const char* boolPropertyKey = NULL, mitk::BaseRenderer* renderer = NULL, const char* boolPropertyKey2 = NULL); 00292 00293 //##Documentation 00294 //## \brief Compute the bounding box of all visible parts of the data tree structure, for general 00295 //## rendering or renderer specific visibility property checking 00296 //## 00297 //## Simply calls ComputeBoundingBox(it, "visible", renderer, boolPropertyKey). 00298 //## it -> an iterator of a data tree structure 00299 //## @param renderer the reference to the renderer 00300 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00301 //## and is set to @a false, the node is ignored for the bounding-box calculation. 00302 mitk::BoundingBox::Pointer ComputeVisibleBoundingBox( mitk::BaseRenderer* renderer = NULL, const char* boolPropertyKey = NULL) 00303 { 00304 return ComputeBoundingBox( "visible", renderer, boolPropertyKey); 00305 } 00306 00307 //##Documentation 00308 //## @brief Compute the time-bounds of the contents of a data tree structure 00309 //## 00310 //## The methods returns only [-infinity, +infinity], if all data-objects have an infinite live-span. Otherwise, 00311 //## all data-objects with infinite live-span are ignored. 00312 //## it -> an iterator to a data tree structure 00313 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00314 //## and is set to @a false, the node is ignored for the time-bounds calculation. 00315 //## @param renderer see @a boolPropertyKey 00316 //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey 00317 mitk::TimeBounds ComputeTimeBounds( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2); 00318 00319 //##Documentation 00320 //## @brief Compute the time-bounds of all visible parts of the data tree structure, for general 00321 //## rendering or renderer specific visibility property checking 00322 //## 00323 //## The methods returns only [-infinity, +infinity], if all data-objects have an infinite live-span. Otherwise, 00324 //## all data-objects with infinite live-span are ignored. 00325 //## Simply calls ComputeTimeBounds(it, "visible", renderer, boolPropertyKey). 00326 //## @param it an iterator to a data tree structure 00327 //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer) 00328 //## and is set to @a false, the node is ignored for the time-bounds calculation. 00329 //## @param renderer see @a boolPropertyKey 00330 mitk::TimeBounds ComputeTimeBounds( mitk::BaseRenderer* renderer, const char* boolPropertyKey) 00331 { 00332 return ComputeTimeBounds( "visible", renderer, boolPropertyKey); 00333 } 00334 00335 protected: 00336 //##Documentation 00337 //## @brief EmitAddNodeEvent emits the AddNodeEvent 00338 //## 00339 //## This method should be called by subclasses to emit the AddNodeEvent 00340 void EmitAddNodeEvent(const mitk::DataNode* node); 00341 00342 //##Documentation 00343 //## @brief EmitRemoveNodeEvent emits the RemoveNodeEvent 00344 //## 00345 //## This method should be called by subclasses to emit the RemoveNodeEvent 00346 void EmitRemoveNodeEvent(const mitk::DataNode* node); 00347 00348 //##Documentation 00349 //## @brief OnNodeModified listens to modified events of DataNodes. 00350 //## 00351 //## The node is hidden behind the caller parameter, which has to be casted first. 00352 //## If the cast succeeds the ChangedNodeEvent is emitted with this node. 00353 void OnNodeModifiedOrDeleted( const itk::Object *caller, const itk::EventObject &event ); 00354 00355 //##Documentation 00356 //## @brief Adds a Modified-Listener to the given Node. 00357 void AddListeners(const mitk::DataNode* _Node); 00358 00359 //##Documentation 00360 //## @brief Removes a Modified-Listener from the given Node. 00361 void RemoveListeners(const mitk::DataNode* _Node); 00362 00363 00364 00365 //##Documentation 00366 //## @brief Saves Modified-Observer Tags for each node in order to remove the event listeners again. 00367 std::map<const mitk::DataNode*, unsigned long> m_NodeModifiedObserverTags; 00368 00369 //##Documentation 00370 //## @brief Saves Delete-Observer Tags for each node in order to remove the event listeners again. 00371 std::map<const mitk::DataNode*, unsigned long> m_NodeDeleteObserverTags; 00372 00373 //##Documentation 00374 //## @brief If this class changes nodes itself, set this to TRUE in order 00375 //## to suppress NodeChangedEvent to be emitted. 00376 bool m_BlockNodeModifiedEvents; 00377 00378 //##Documentation 00379 //## @brief Standard Constructor for ::New() instantiation 00380 DataStorage(); 00381 //##Documentation 00382 //## @brief Standard Destructor 00383 virtual ~DataStorage(); 00384 00385 //##Documentation 00386 //## @brief Filters a SetOfObjects by the condition. If no condition is provided, the original set is returned 00387 SetOfObjects::ConstPointer FilterSetOfObjects(const SetOfObjects* set, const NodePredicateBase* condition) const; 00388 00389 //##Documentation 00390 //## @brief Prints the contents of the DataStorage to os. Do not call directly, call ->Print() instead 00391 virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; 00392 }; 00393 } // namespace mitk 00394 00395 #endif /* MITKDATASTORAGE_H_HEADER_INCLUDED_ */