Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 #include "mitkPersistenceService.h"
14 #include "mitkProperties.h"
16 #include "mitkUIDGenerator.h"
17 #include "usGetModuleContext.h"
18 #include "usModuleContext.h"
19 #include <itksys/SystemTools.hxx>
20 
22 {
23  return "PersistenceNode";
24 }
25 
27 {
28  return "PersistenceService";
29 }
30 
31 mitk::PersistenceService::PersistenceService() : m_AutoLoadAndSave(true), m_Initialized(false), m_InInitialized(false)
32 {
33 }
34 
36 {
37  this->Initialize();
38  m_PropertyLists.clear();
39  m_FileNamesToModifiedTimes.clear();
40 }
41 
43 {
44  MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService";
45 }
46 
48 {
49  this->Initialize();
50  std::string file = "PersistentData.xml";
51  us::ModuleContext *context = us::GetModuleContext();
52  std::string contextDataFile = context->GetDataFile(file);
53 
54  if (!contextDataFile.empty())
55  {
56  file = contextDataFile;
57  }
58  return file;
59 }
60 
62 {
63  this->Initialize();
65 
66  if (id.empty())
67  {
68  UIDGenerator uidGen;
69  id = uidGen.GetUID();
70  }
71 
72  auto it = m_PropertyLists.find(id);
73  if (it == m_PropertyLists.end())
74  {
75  propList = PropertyList::New();
76  m_PropertyLists[id] = propList;
77  if (existed)
78  *existed = false;
79  }
80  else
81  {
82  propList = (*it).second;
83  if (existed)
84  *existed = true;
85  }
86 
87  return propList;
88 }
89 
90 void mitk::PersistenceService::ClonePropertyList(mitk::PropertyList *from, mitk::PropertyList *to) const
91 {
92  to->Clear();
93 
94  const std::map<std::string, BaseProperty::Pointer> *propMap = from->GetMap();
95  auto propMapIt = propMap->begin();
96  while (propMapIt != propMap->end())
97  {
98  mitk::BaseProperty::Pointer clonedProp = (*propMapIt).second->Clone();
99  to->SetProperty((*propMapIt).first, clonedProp);
100  ++propMapIt;
101  }
102 }
103 
104 bool mitk::PersistenceService::Save(const std::string &fileName, bool appendChanges)
105 {
106  this->Initialize();
107  bool save = false;
108  std::string theFile = fileName;
109  if (theFile.empty())
111 
112  std::string thePath = itksys::SystemTools::GetFilenamePath(theFile.c_str());
113  if (!thePath.empty() && !itksys::SystemTools::FileExists(thePath.c_str()))
114  {
115  if (!itksys::SystemTools::MakeDirectory(thePath.c_str()))
116  {
117  MITK_ERROR("PersistenceService") << "Could not create " << thePath;
118  return false;
119  }
120  }
121 
122  bool createFile = !itksys::SystemTools::FileExists(theFile.c_str());
123  if (!itksys::SystemTools::Touch(theFile.c_str(), createFile))
124  {
125  MITK_ERROR("PersistenceService") << "Could not create or write to " << theFile;
126  return false;
127  }
128 
129  bool xmlFile = false;
130  if (itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml")
131  xmlFile = true;
132 
134  if (appendChanges)
135  {
136  if (xmlFile == false)
137  {
138  if (itksys::SystemTools::FileExists(theFile.c_str()))
139  {
140  bool load = false;
141  DataStorage::Pointer ds = m_SceneIO->LoadScene(theFile);
142  load = (m_SceneIO->GetFailedNodes() == nullptr || m_SceneIO->GetFailedNodes()->size() == 0) &&
143  (m_SceneIO->GetFailedNodes() == nullptr || m_SceneIO->GetFailedProperties()->IsEmpty());
144  if (!load)
145  return false;
146 
147  tempDs = ds;
148  }
149  }
150  else
151  {
153  if (xmlFile && appendChanges && itksys::SystemTools::FileExists(theFile.c_str()))
154  {
155  if (!m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists))
156  return false;
157  }
158  }
159 
161  }
162  else if (xmlFile == false)
163  {
165  }
166 
167  if (xmlFile)
168  {
169  save = m_PropertyListsXmlFileReaderAndWriter->WriteLists(theFile, m_PropertyLists);
170  }
171 
172  else
173  {
174  DataStorage::SetOfObjects::Pointer sceneNodes = this->GetDataNodes(tempDs);
175  if (m_SceneIO.IsNull())
176  {
177  m_SceneIO = mitk::SceneIO::New();
178  }
179  save = m_SceneIO->SaveScene(sceneNodes.GetPointer(), tempDs, theFile);
180  }
181  if (save)
182  {
183  long int currentModifiedTime = itksys::SystemTools::ModifiedTime(theFile.c_str());
184  m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
185  }
186 
187  return save;
188 }
189 
190 bool mitk::PersistenceService::Load(const std::string &fileName, bool enforceReload)
191 {
192  this->Initialize();
193  bool load = false;
194 
195  std::string theFile = fileName;
196  if (theFile.empty())
198 
199  MITK_DEBUG << "Load persistence data from file: " << theFile;
200 
201  if (!itksys::SystemTools::FileExists(theFile.c_str()))
202  return false;
203 
204  bool xmlFile = false;
205  if (itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml")
206  xmlFile = true;
207 
208  if (enforceReload == false)
209  {
210  bool loadTheFile = true;
211  auto it = m_FileNamesToModifiedTimes.find(theFile);
212 
213  long int currentModifiedTime = itksys::SystemTools::ModifiedTime(theFile.c_str());
214  if (it != m_FileNamesToModifiedTimes.end())
215  {
216  long int knownModifiedTime = (*it).second;
217  if (knownModifiedTime >= currentModifiedTime)
218  {
219  loadTheFile = false;
220  }
221  }
222  if (loadTheFile)
223  m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
224  else
225  return true;
226  }
227 
228  if (xmlFile)
229  {
230  load = m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists);
231  }
232  else
233  {
234  if (m_SceneIO.IsNull())
235  {
236  m_SceneIO = mitk::SceneIO::New();
237  }
238  DataStorage::Pointer ds = m_SceneIO->LoadScene(theFile);
239  load = (m_SceneIO->GetFailedNodes() == nullptr || m_SceneIO->GetFailedNodes()->size() == 0) &&
240  (m_SceneIO->GetFailedNodes() == nullptr || m_SceneIO->GetFailedProperties()->IsEmpty());
241  if (load)
242  {
244  }
245  }
246  if (!load)
247  {
248  MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed";
249  return load;
250  }
251 
252  return load;
253 }
254 
256 {
257  this->Initialize();
258  m_AutoLoadAndSave = autoLoadAndSave;
259  // std::string id = PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
260  std::string id = GetPersistencePropertyListName();
261  mitk::PropertyList::Pointer propList = this->GetPropertyList(id);
262  propList->Set("m_AutoLoadAndSave", m_AutoLoadAndSave);
263  this->Save();
264 }
265 
267 {
268  this->Initialize();
269  m_PropertyListReplacedObserver.insert(observer);
270 }
271 
273 {
274  this->Initialize();
275  m_PropertyListReplacedObserver.erase(observer);
276 }
277 
279 {
280  MITK_DEBUG << "Persistence Module loaded.";
281 }
282 
284 {
285  return us::GetModuleContext();
286 }
287 
289 {
290  this->Initialize();
291  // return PERSISTENCE_PROPERTY_NAME; //see bug 17729
293 }
294 mitk::DataStorage::SetOfObjects::Pointer mitk::PersistenceService::GetDataNodes(mitk::DataStorage *ds)
295 {
296  this->Initialize();
297  DataStorage::SetOfObjects::Pointer set = DataStorage::SetOfObjects::New();
298 
299  std::map<std::string, mitk::PropertyList::Pointer>::const_iterator it = m_PropertyLists.begin();
300  while (it != m_PropertyLists.end())
301  {
303  const std::string &name = (*it).first;
304 
305  this->ClonePropertyList((*it).second, node->GetPropertyList());
306 
307  node->SetName(name);
308  MITK_DEBUG << "Persistence Property Name: " << GetPersistencePropertyName().c_str();
309  // node->SetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str() , true ); //see bug 17729
310  node->SetBoolProperty(GetPersistencePropertyName().c_str(), true);
311 
312  ds->Add(node);
313  set->push_back(node);
314  ++it;
315  }
316 
317  return set;
318 }
319 
321 {
322  this->Initialize();
323  bool oneFound = false;
324  DataStorage::SetOfObjects::ConstPointer allNodes = storage->GetAll();
325  for (auto sourceIter = allNodes->begin(); sourceIter != allNodes->end();
326  ++sourceIter)
327  {
328  mitk::DataNode *node = *sourceIter;
329  bool isPersistenceNode = false;
330  // node->GetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str(), isPersistenceNode ); //see bug 17729
331  node->GetBoolProperty(GetPersistencePropertyName().c_str(), isPersistenceNode);
332 
333  if (isPersistenceNode)
334  {
335  oneFound = true;
336  MITK_DEBUG("mitk::PersistenceService") << "isPersistenceNode was true";
337  std::string name = node->GetName();
338 
339  bool existed = false;
340  mitk::PropertyList::Pointer propList = this->GetPropertyList(name, &existed);
341 
342  if (existed)
343  {
344  MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values";
345  auto it = m_PropertyListReplacedObserver.begin();
346  while (it != m_PropertyListReplacedObserver.end())
347  {
348  (*it)->BeforePropertyListReplaced(name, propList);
349  ++it;
350  }
351  } // if( existed )
352 
353  MITK_DEBUG("mitk::PersistenceService") << "replacing values";
354 
355  this->ClonePropertyList(node->GetPropertyList(), propList);
356 
357  if (existed)
358  {
359  MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values";
360  auto it = m_PropertyListReplacedObserver.begin();
361  while (it != m_PropertyListReplacedObserver.end())
362  {
363  (*it)->AfterPropertyListReplaced(name, propList);
364  ++it;
365  }
366  } // if( existed )
367  } // if( isPersistenceNode )
368  } // for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = allNodes->begin(); ...
369 
370  return oneFound;
371 }
372 
374 {
375  this->Initialize();
376  return m_AutoLoadAndSave;
377 }
378 
380 {
381  this->Initialize();
382  auto it = m_PropertyLists.find(id);
383  if (it != m_PropertyLists.end())
384  {
385  m_PropertyLists.erase(it);
386  return true;
387  }
388  return false;
389 }
390 
391 void mitk::PersistenceService::Initialize()
392 {
393  if (m_Initialized || m_InInitialized)
394  return;
395  m_InInitialized = true;
396 
397  m_PropertyListsXmlFileReaderAndWriter = PropertyListsXmlFileReaderAndWriter::New();
398 
399  // Load Default File in any case
400  this->Load();
401  // std::string id = mitk::PersistenceService::PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
402  std::string id = GetPersistencePropertyListName();
403  mitk::PropertyList::Pointer propList = this->GetPropertyList(id);
404  bool autoLoadAndSave = true;
405  propList->GetBoolProperty("m_AutoLoadAndSave", autoLoadAndSave);
406 
407  if (autoLoadAndSave == false)
408  {
409  MITK_DEBUG("mitk::PersistenceService") << "autoloading was not wished. clearing data we got so far.";
410  this->SetAutoLoadAndSave(false);
411  this->Clear();
412  }
413 
414  m_InInitialized = false;
415  m_Initialized = true;
416 }
417 
419 {
420  if (this->GetAutoLoadAndSave())
421  this->Save();
422 }
Data management class that handles &#39;was created by&#39; relations.
static Pointer New()
Generated unique IDs.
void SetAutoLoadAndSave(bool autoLoadAndSave) override
static us::ModuleContext * GetModuleContext()
#define MITK_ERROR
Definition: mitkLogMacros.h:20
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
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()
bool GetBoolProperty(const char *propertyKey, bool &boolValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for bool properties (instances of BoolProperty)
virtual void Add(DataNode *node, const DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
static Pointer New()
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
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
static Pointer New()
static std::string GetPersistencePropertyListName()
bool RemovePropertyList(std::string &id) override
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is nullptr, the BaseRenderer-independent PropertyLi...
DataStorage::SetOfObjects::Pointer GetDataNodes(DataStorage *ds=nullptr) override
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
mitk::PropertyList::Pointer GetPropertyList(std::string &id, bool *existed=nullptr) override
std::string GetDefaultPersistenceFile() override
Class for nodes of the DataTree.
Definition: mitkDataNode.h:64
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:376
const PropertyMap * GetMap() const