Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkPersistenceService.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 #include "mitkPersistenceService.h"
18 #include "mitkProperties.h"
20 #include "mitkUIDGenerator.h"
21 #include "usGetModuleContext.h"
22 #include "usModuleContext.h"
23 #include <itksys/SystemTools.hxx>
24 
26 {
27  return "PersistenceNode";
28 }
29 
31 {
32  return "PersistenceService";
33 }
34 
35 mitk::PersistenceService::PersistenceService() : m_AutoLoadAndSave(true), m_Initialized(false), m_InInitialized(false)
36 {
37 }
38 
40 {
41  this->Initialize();
42  m_PropertyLists.clear();
43  m_FileNamesToModifiedTimes.clear();
44 }
45 
47 {
48  MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService";
49 }
50 
52 {
53  this->Initialize();
54  std::string file = "PersistentData.xml";
55  us::ModuleContext *context = us::GetModuleContext();
56  std::string contextDataFile = context->GetDataFile(file);
57 
58  if (!contextDataFile.empty())
59  {
60  file = contextDataFile;
61  }
62  return file;
63 }
64 
66 {
67  this->Initialize();
69 
70  if (id.empty())
71  {
72  UIDGenerator uidGen;
73  id = uidGen.GetUID();
74  }
75 
76  std::map<std::string, mitk::PropertyList::Pointer>::iterator it = m_PropertyLists.find(id);
77  if (it == m_PropertyLists.end())
78  {
79  propList = PropertyList::New();
80  m_PropertyLists[id] = propList;
81  if (existed)
82  *existed = false;
83  }
84  else
85  {
86  propList = (*it).second;
87  if (existed)
88  *existed = true;
89  }
90 
91  return propList;
92 }
93 
94 void mitk::PersistenceService::ClonePropertyList(mitk::PropertyList *from, mitk::PropertyList *to) const
95 {
96  to->Clear();
97 
98  const std::map<std::string, BaseProperty::Pointer> *propMap = from->GetMap();
99  std::map<std::string, BaseProperty::Pointer>::const_iterator propMapIt = propMap->begin();
100  while (propMapIt != propMap->end())
101  {
102  mitk::BaseProperty::Pointer clonedProp = (*propMapIt).second->Clone();
103  to->SetProperty((*propMapIt).first, clonedProp);
104  ++propMapIt;
105  }
106 }
107 
108 bool mitk::PersistenceService::Save(const std::string &fileName, bool appendChanges)
109 {
110  this->Initialize();
111  bool save = false;
112  std::string theFile = fileName;
113  if (theFile.empty())
115 
116  std::string thePath = itksys::SystemTools::GetFilenamePath(theFile.c_str());
117  if (!thePath.empty() && !itksys::SystemTools::FileExists(thePath.c_str()))
118  {
119  if (!itksys::SystemTools::MakeDirectory(thePath.c_str()))
120  {
121  MITK_ERROR("PersistenceService") << "Could not create " << thePath;
122  return false;
123  }
124  }
125 
126  bool createFile = !itksys::SystemTools::FileExists(theFile.c_str());
127  if (!itksys::SystemTools::Touch(theFile.c_str(), createFile))
128  {
129  MITK_ERROR("PersistenceService") << "Could not create or write to " << theFile;
130  return false;
131  }
132 
133  bool xmlFile = false;
134  if (itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml")
135  xmlFile = true;
136 
138  if (appendChanges)
139  {
140  if (xmlFile == false)
141  {
142  if (itksys::SystemTools::FileExists(theFile.c_str()))
143  {
144  bool load = false;
145  DataStorage::Pointer ds = m_SceneIO->LoadScene(theFile);
146  load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) &&
147  (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
148  if (!load)
149  return false;
150 
151  tempDs = ds;
152  }
153  }
154  else
155  {
157  if (xmlFile && appendChanges && itksys::SystemTools::FileExists(theFile.c_str()))
158  {
159  if (!m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists))
160  return false;
161  }
162  }
163 
164  this->RestorePropertyListsFromPersistentDataNodes(tempDs);
165  }
166  else if (xmlFile == false)
167  {
169  }
170 
171  if (xmlFile)
172  {
173  save = m_PropertyListsXmlFileReaderAndWriter->WriteLists(theFile, m_PropertyLists);
174  }
175 
176  else
177  {
178  DataStorage::SetOfObjects::Pointer sceneNodes = this->GetDataNodes(tempDs);
179  if (m_SceneIO.IsNull())
180  {
181  m_SceneIO = mitk::SceneIO::New();
182  }
183  save = m_SceneIO->SaveScene(sceneNodes.GetPointer(), tempDs, theFile);
184  }
185  if (save)
186  {
187  long int currentModifiedTime = itksys::SystemTools::ModifiedTime(theFile.c_str());
188  m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
189  }
190 
191  return save;
192 }
193 
194 bool mitk::PersistenceService::Load(const std::string &fileName, bool enforceReload)
195 {
196  this->Initialize();
197  bool load = false;
198 
199  std::string theFile = fileName;
200  if (theFile.empty())
202 
203  MITK_DEBUG << "Load persistence data from file: " << theFile;
204 
205  if (!itksys::SystemTools::FileExists(theFile.c_str()))
206  return false;
207 
208  bool xmlFile = false;
209  if (itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml")
210  xmlFile = true;
211 
212  if (enforceReload == false)
213  {
214  bool loadTheFile = true;
215  std::map<std::string, long int>::iterator it = m_FileNamesToModifiedTimes.find(theFile);
216 
217  long int currentModifiedTime = itksys::SystemTools::ModifiedTime(theFile.c_str());
218  if (it != m_FileNamesToModifiedTimes.end())
219  {
220  long int knownModifiedTime = (*it).second;
221  if (knownModifiedTime >= currentModifiedTime)
222  {
223  loadTheFile = false;
224  }
225  }
226  if (loadTheFile)
227  m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
228  else
229  return true;
230  }
231 
232  if (xmlFile)
233  {
234  load = m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists);
235  }
236  else
237  {
238  if (m_SceneIO.IsNull())
239  {
240  m_SceneIO = mitk::SceneIO::New();
241  }
242  DataStorage::Pointer ds = m_SceneIO->LoadScene(theFile);
243  load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) &&
244  (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
245  if (load)
246  {
247  this->RestorePropertyListsFromPersistentDataNodes(ds);
248  }
249  }
250  if (!load)
251  {
252  MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed";
253  return load;
254  }
255 
256  return load;
257 }
258 
260 {
261  this->Initialize();
262  m_AutoLoadAndSave = autoLoadAndSave;
263  // std::string id = PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
264  std::string id = GetPersistencePropertyListName();
265  mitk::PropertyList::Pointer propList = this->GetPropertyList(id);
266  propList->Set("m_AutoLoadAndSave", m_AutoLoadAndSave);
267  this->Save();
268 }
269 
271 {
272  this->Initialize();
273  m_PropertyListReplacedObserver.insert(observer);
274 }
275 
277 {
278  this->Initialize();
279  m_PropertyListReplacedObserver.erase(observer);
280 }
281 
283 {
284  MITK_DEBUG << "Persistence Module loaded.";
285 }
286 
288 {
289  return us::GetModuleContext();
290 }
291 
293 {
294  this->Initialize();
295  // return PERSISTENCE_PROPERTY_NAME; //see bug 17729
296  return GetPersistencePropertyName();
297 }
299 {
300  this->Initialize();
302 
303  std::map<std::string, mitk::PropertyList::Pointer>::const_iterator it = m_PropertyLists.begin();
304  while (it != m_PropertyLists.end())
305  {
307  const std::string &name = (*it).first;
308 
309  this->ClonePropertyList((*it).second, node->GetPropertyList());
310 
311  node->SetName(name);
312  MITK_DEBUG << "Persistence Property Name: " << GetPersistencePropertyName().c_str();
313  // node->SetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str() , true ); //see bug 17729
314  node->SetBoolProperty(GetPersistencePropertyName().c_str(), true);
315 
316  ds->Add(node);
317  set->push_back(node);
318  ++it;
319  }
320 
321  return set;
322 }
323 
325 {
326  this->Initialize();
327  bool oneFound = false;
328  DataStorage::SetOfObjects::ConstPointer allNodes = storage->GetAll();
329  for (mitk::DataStorage::SetOfObjects::const_iterator sourceIter = allNodes->begin(); sourceIter != allNodes->end();
330  ++sourceIter)
331  {
332  mitk::DataNode *node = *sourceIter;
333  bool isPersistenceNode = false;
334  // node->GetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str(), isPersistenceNode ); //see bug 17729
335  node->GetBoolProperty(GetPersistencePropertyName().c_str(), isPersistenceNode);
336 
337  if (isPersistenceNode)
338  {
339  oneFound = true;
340  MITK_DEBUG("mitk::PersistenceService") << "isPersistenceNode was true";
341  std::string name = node->GetName();
342 
343  bool existed = false;
344  mitk::PropertyList::Pointer propList = this->GetPropertyList(name, &existed);
345 
346  if (existed)
347  {
348  MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values";
349  std::set<PropertyListReplacedObserver *>::iterator it = m_PropertyListReplacedObserver.begin();
350  while (it != m_PropertyListReplacedObserver.end())
351  {
352  (*it)->BeforePropertyListReplaced(name, propList);
353  ++it;
354  }
355  } // if( existed )
356 
357  MITK_DEBUG("mitk::PersistenceService") << "replacing values";
358 
359  this->ClonePropertyList(node->GetPropertyList(), propList);
360 
361  if (existed)
362  {
363  MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values";
364  std::set<PropertyListReplacedObserver *>::iterator it = m_PropertyListReplacedObserver.begin();
365  while (it != m_PropertyListReplacedObserver.end())
366  {
367  (*it)->AfterPropertyListReplaced(name, propList);
368  ++it;
369  }
370  } // if( existed )
371  } // if( isPersistenceNode )
372  } // for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = allNodes->begin(); ...
373 
374  return oneFound;
375 }
376 
378 {
379  this->Initialize();
380  return m_AutoLoadAndSave;
381 }
382 
384 {
385  this->Initialize();
386  std::map<std::string, mitk::PropertyList::Pointer>::iterator it = m_PropertyLists.find(id);
387  if (it != m_PropertyLists.end())
388  {
389  m_PropertyLists.erase(it);
390  return true;
391  }
392  return false;
393 }
394 
395 void mitk::PersistenceService::Initialize()
396 {
397  if (m_Initialized || m_InInitialized)
398  return;
399  m_InInitialized = true;
400 
401  m_PropertyListsXmlFileReaderAndWriter = PropertyListsXmlFileReaderAndWriter::New();
402 
403  // Load Default File in any case
404  this->Load();
405  // std::string id = mitk::PersistenceService::PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
406  std::string id = GetPersistencePropertyListName();
407  mitk::PropertyList::Pointer propList = this->GetPropertyList(id);
408  bool autoLoadAndSave = true;
409  propList->GetBoolProperty("m_AutoLoadAndSave", autoLoadAndSave);
410 
411  if (autoLoadAndSave == false)
412  {
413  MITK_DEBUG("mitk::PersistenceService") << "autoloading was not wished. clearing data we got so far.";
414  this->SetAutoLoadAndSave(false);
415  this->Clear();
416  }
417 
418  m_InInitialized = false;
419  m_Initialized = true;
420 }
421 
423 {
424  if (this->GetAutoLoadAndSave())
425  this->Save();
426 }
DataStorage::SetOfObjects::Pointer GetDataNodes(DataStorage *ds=0) override
virtual void Add(mitk::DataNode *node, const mitk::DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is NULL, the BaseRenderer-independent PropertyList ...
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
static Pointer New()
Generated unique IDs.
void SetAutoLoadAndSave(bool autoLoadAndSave) override
static us::ModuleContext * GetModuleContext()
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void SetProperty(const std::string &propertyKey, BaseProperty *property)
Set a property in the list/map by value.
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
Definition: mitkDataNode.h:366
bool GetBoolProperty(const char *propertyKey, bool &boolValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for bool properties (instances of BoolProperty)
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
void AddPropertyListReplacedObserver(PropertyListReplacedObserver *observer) override
Key-value list holding instances of BaseProperty.
bool Save(const std::string &fileName="", bool appendChanges=false) override
bool Load(const std::string &fileName="", bool enforeReload=true) override
static std::string GetPersistencePropertyName()
static Pointer New()
itk::SmartPointer< const Self > ConstPointer
void RemovePropertyListReplacedObserver(PropertyListReplacedObserver *observer) override
std::string GetPersistenceNodePropertyName() override
virtual SetOfObjects::ConstPointer GetAll() const =0
returns a set of all data objects that are stored in the data storage
bool RestorePropertyListsFromPersistentDataNodes(const DataStorage *storage) override
static Pointer New()
static std::string GetPersistencePropertyListName()
bool RemovePropertyList(std::string &id) override
mitk::PropertyList::Pointer GetPropertyList(std::string &id, bool *existed=0) override
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
std::string GetDefaultPersistenceFile() override
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
const PropertyMap * GetMap() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.