Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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.