<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "mitkPersistenceService.h"
#include "mitkStandaloneDataStorage.h"
#include "mitkUIDGenerator.h"
#include "mitkNodePredicateProperty.h"
#include "mitkProperties.h"
#include "usModuleContext.h"
#include "usGetModuleContext.h"
#include <itksys/SystemTools.hxx>

std::string mitk::PersistenceService::GetPersistencePropertyName()
{
  return "PersistenceNode";
}

std::string mitk::PersistenceService::GetPersistencePropertyListName()
{
  return "PersistenceService";
}

mitk::PersistenceService::PersistenceService()
: m_AutoLoadAndSave( true ), m_Initialized(false), m_InInitialized(false)
{
}

void mitk::PersistenceService::Clear()
{
  this->Initialize();
  m_PropertyLists.clear();
  m_FileNamesToModifiedTimes.clear();
}

mitk::PersistenceService::~PersistenceService()
{
  MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService";
}

std::string mitk::PersistenceService::GetDefaultPersistenceFile()
{
  this->Initialize();
  std::string file = "PersistentData.xml";
  us::ModuleContext* context = us::GetModuleContext();
  std::string contextDataFile = context->GetDataFile(file);

  if( !contextDataFile.empty() )
  {
      file = contextDataFile;
  }
  return file;
}

mitk::PropertyList::Pointer mitk::PersistenceService::GetPropertyList( std::string& id, bool* existed )
{
  this->Initialize();
  mitk::PropertyList::Pointer propList;

  if( id.empty() )
  {
      UIDGenerator uidGen;
      id = uidGen.GetUID();
  }

  std::map<std::string, mitk::PropertyList::Pointer>::iterator it = m_PropertyLists.find( id );
  if( it == m_PropertyLists.end() )
  {
      propList = PropertyList::New();
      m_PropertyLists[id] = propList;
      if( existed )
          *existed = false;
  }
  else
  {
      propList = (*it).second;
      if( existed )
          *existed = true;
  }

  return propList;
}

void mitk::PersistenceService::ClonePropertyList( mitk::PropertyList* from, mitk::PropertyList* to ) const
{
  to->Clear();

  const std::map< std::string, BaseProperty::Pointer>* propMap = from->GetMap();
  std::map< std::string, BaseProperty::Pointer>::const_iterator propMapIt = propMap->begin();
  while( propMapIt != propMap->end() )
  {
      mitk::BaseProperty::Pointer clonedProp = (*propMapIt).second->Clone();
      to->SetProperty( (*propMapIt).first, clonedProp );
      ++propMapIt;
  }
}

bool mitk::PersistenceService::Save(const std::string& fileName, bool appendChanges)
{
  this->Initialize();
  bool save = false;
  std::string theFile = fileName;
  if(theFile.empty())
      theFile = PersistenceService::GetDefaultPersistenceFile();

  std::string thePath = itksys::SystemTools::GetFilenamePath( theFile.c_str() );
  if( !thePath.empty() && !itksys::SystemTools::FileExists( thePath.c_str() ) )
  {
    if( !itksys::SystemTools::MakeDirectory( thePath.c_str() ) )
    {
      MITK_ERROR("PersistenceService") << "Could not create " << thePath;
      return false;
    }
  }

  bool createFile = !itksys::SystemTools::FileExists(theFile.c_str());
  if( !itksys::SystemTools::Touch(theFile.c_str(), createFile) )
  {
    MITK_ERROR("PersistenceService") << "Could not create or write to " << theFile;
    return false;
  }

  bool xmlFile = false;
  if( itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml" )
      xmlFile = true;

  mitk::DataStorage::Pointer tempDs;
  if( appendChanges )
  {
      if(xmlFile == false)
      {
          if( itksys::SystemTools::FileExists(theFile.c_str()) )
          {

              bool load = false;
              DataStorage::Pointer ds = m_SceneIO->LoadScene( theFile );
              load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) && (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
              if( !load )
                  return false;

              tempDs = ds;

          }
      }
      else
      {
          tempDs = mitk::StandaloneDataStorage::New();
          if( xmlFile && appendChanges && itksys::SystemTools::FileExists(theFile.c_str()) )
          {
              if( !m_PropertyListsXmlFileReaderAndWriter->ReadLists( theFile, m_PropertyLists ) )
                  return false;
          }
      }

      this->RestorePropertyListsFromPersistentDataNodes( tempDs );
  }
  else if( xmlFile == false )
  {
      tempDs = mitk::StandaloneDataStorage::New();
  }

  if( xmlFile )
  {
      save = m_PropertyListsXmlFileReaderAndWriter->WriteLists(theFile, m_PropertyLists);
  }

  else
  {
      DataStorage::SetOfObjects::Pointer sceneNodes = this->GetDataNodes(tempDs);
      if(m_SceneIO.IsNull())
      {
        m_SceneIO = mitk::SceneIO::New();
      }
      save = m_SceneIO->SaveScene( sceneNodes.GetPointer(), tempDs, theFile );
  }
  if( save )
  {
      long int currentModifiedTime = itksys::SystemTools::ModifiedTime( theFile.c_str() );
      m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
  }

  return save;
}

bool mitk::PersistenceService::Load(const std::string& fileName, bool enforceReload)
{
  this->Initialize();
  bool load = false;

  std::string theFile = fileName;
  if(theFile.empty())
      theFile = PersistenceService::GetDefaultPersistenceFile();

  MITK_INFO << "Load persistence data from file: " << theFile;

  if( !itksys::SystemTools::FileExists(theFile.c_str()) )
      return false;

  bool xmlFile = false;
  if( itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml" )
      xmlFile = true;

  if( enforceReload == false )
  {
      bool loadTheFile = true;
      std::map<std::string, long int>::iterator it = m_FileNamesToModifiedTimes.find( theFile );

      long int currentModifiedTime = itksys::SystemTools::ModifiedTime( theFile.c_str() );
      if( it != m_FileNamesToModifiedTimes.end() )
      {
          long int knownModifiedTime = (*it).second;
          if( knownModifiedTime >= currentModifiedTime )
          {
              loadTheFile = false;
          }
      }
      if( loadTheFile )
          m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
      else
          return true;
  }

  if( xmlFile )
  {
      load = m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists);
  }
  else
  {
    if(m_SceneIO.IsNull())
    {
      m_SceneIO = mitk::SceneIO::New();
    }
      DataStorage::Pointer ds = m_SceneIO->LoadScene( theFile );
      load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) && (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
      if( load )
      {
          this->RestorePropertyListsFromPersistentDataNodes( ds );
      }
  }
  if( !load )
  {
      MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed";
      return load;
  }

  return load;
}

void mitk::PersistenceService::SetAutoLoadAndSave(bool autoLoadAndSave)
{
  this->Initialize();
  m_AutoLoadAndSave = autoLoadAndSave;
  //std::string id = PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
  std::string id = GetPersistencePropertyListName();
  mitk::PropertyList::Pointer propList = this->GetPropertyList( id );
  propList->Set("m_AutoLoadAndSave", m_AutoLoadAndSave);
  this->Save();
}

void mitk::PersistenceService::AddPropertyListReplacedObserver(PropertyListReplacedObserver* observer)
{
  this->Initialize();
  m_PropertyListReplacedObserver.insert( observer );
}

void mitk::PersistenceService::RemovePropertyListReplacedObserver(PropertyListReplacedObserver* observer)
{
  this->Initialize();
  m_PropertyListReplacedObserver.erase( observer );
}

void mitk::PersistenceService::LoadModule()
{
    MITK_INFO << "Persistence Module loaded.";
}

us::ModuleContext* mitk::PersistenceService::GetModuleContext()
{
  return us::GetModuleContext();
}

std::string mitk::PersistenceService::GetPersistenceNodePropertyName()
{
  this->Initialize();
  //return PERSISTENCE_PROPERTY_NAME; //see bug 17729
  return GetPersistencePropertyName();
}
mitk::DataStorage::SetOfObjects::Pointer mitk::PersistenceService::GetDataNodes(mitk::DataStorage* ds)
{
  this->Initialize();
  DataStorage::SetOfObjects::Pointer set = DataStorage::SetOfObjects::New();

  std::map<std::string, mitk::PropertyList::Pointer>::const_iterator it = m_PropertyLists.begin();
  while( it != m_PropertyLists.end() )
  {
      mitk::DataNode::Pointer node = mitk::DataNode::New();
      const std::string& name = (*it).first;

      this->ClonePropertyList( (*it).second, node->GetPropertyList() );


      node->SetName( name );<commit_msg>PersistenceService output MITK_DEBUG, not MITK_INFO, so its silent on startup<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/
#include "mitkPersistenceService.h"
#include "mitkStandaloneDataStorage.h"
#include "mitkUIDGenerator.h"
#include "mitkNodePredicateProperty.h"
#include "mitkProperties.h"
#include "usModuleContext.h"
#include "usGetModuleContext.h"
#include <itksys/SystemTools.hxx>

std::string mitk::PersistenceService::GetPersistencePropertyName()
{
  return "PersistenceNode";
}

std::string mitk::PersistenceService::GetPersistencePropertyListName()
{
  return "PersistenceService";
}

mitk::PersistenceService::PersistenceService()
: m_AutoLoadAndSave( true ), m_Initialized(false), m_InInitialized(false)
{
}

void mitk::PersistenceService::Clear()
{
  this->Initialize();
  m_PropertyLists.clear();
  m_FileNamesToModifiedTimes.clear();
}

mitk::PersistenceService::~PersistenceService()
{
  MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService";
}

std::string mitk::PersistenceService::GetDefaultPersistenceFile()
{
  this->Initialize();
  std::string file = "PersistentData.xml";
  us::ModuleContext* context = us::GetModuleContext();
  std::string contextDataFile = context->GetDataFile(file);

  if( !contextDataFile.empty() )
  {
      file = contextDataFile;
  }
  return file;
}

mitk::PropertyList::Pointer mitk::PersistenceService::GetPropertyList( std::string& id, bool* existed )
{
  this->Initialize();
  mitk::PropertyList::Pointer propList;

  if( id.empty() )
  {
      UIDGenerator uidGen;
      id = uidGen.GetUID();
  }

  std::map<std::string, mitk::PropertyList::Pointer>::iterator it = m_PropertyLists.find( id );
  if( it == m_PropertyLists.end() )
  {
      propList = PropertyList::New();
      m_PropertyLists[id] = propList;
      if( existed )
          *existed = false;
  }
  else
  {
      propList = (*it).second;
      if( existed )
          *existed = true;
  }

  return propList;
}

void mitk::PersistenceService::ClonePropertyList( mitk::PropertyList* from, mitk::PropertyList* to ) const
{
  to->Clear();

  const std::map< std::string, BaseProperty::Pointer>* propMap = from->GetMap();
  std::map< std::string, BaseProperty::Pointer>::const_iterator propMapIt = propMap->begin();
  while( propMapIt != propMap->end() )
  {
      mitk::BaseProperty::Pointer clonedProp = (*propMapIt).second->Clone();
      to->SetProperty( (*propMapIt).first, clonedProp );
      ++propMapIt;
  }
}

bool mitk::PersistenceService::Save(const std::string& fileName, bool appendChanges)
{
  this->Initialize();
  bool save = false;
  std::string theFile = fileName;
  if(theFile.empty())
      theFile = PersistenceService::GetDefaultPersistenceFile();

  std::string thePath = itksys::SystemTools::GetFilenamePath( theFile.c_str() );
  if( !thePath.empty() && !itksys::SystemTools::FileExists( thePath.c_str() ) )
  {
    if( !itksys::SystemTools::MakeDirectory( thePath.c_str() ) )
    {
      MITK_ERROR("PersistenceService") << "Could not create " << thePath;
      return false;
    }
  }

  bool createFile = !itksys::SystemTools::FileExists(theFile.c_str());
  if( !itksys::SystemTools::Touch(theFile.c_str(), createFile) )
  {
    MITK_ERROR("PersistenceService") << "Could not create or write to " << theFile;
    return false;
  }

  bool xmlFile = false;
  if( itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml" )
      xmlFile = true;

  mitk::DataStorage::Pointer tempDs;
  if( appendChanges )
  {
      if(xmlFile == false)
      {
          if( itksys::SystemTools::FileExists(theFile.c_str()) )
          {

              bool load = false;
              DataStorage::Pointer ds = m_SceneIO->LoadScene( theFile );
              load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) && (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
              if( !load )
                  return false;

              tempDs = ds;

          }
      }
      else
      {
          tempDs = mitk::StandaloneDataStorage::New();
          if( xmlFile && appendChanges && itksys::SystemTools::FileExists(theFile.c_str()) )
          {
              if( !m_PropertyListsXmlFileReaderAndWriter->ReadLists( theFile, m_PropertyLists ) )
                  return false;
          }
      }

      this->RestorePropertyListsFromPersistentDataNodes( tempDs );
  }
  else if( xmlFile == false )
  {
      tempDs = mitk::StandaloneDataStorage::New();
  }

  if( xmlFile )
  {
      save = m_PropertyListsXmlFileReaderAndWriter->WriteLists(theFile, m_PropertyLists);
  }

  else
  {
      DataStorage::SetOfObjects::Pointer sceneNodes = this->GetDataNodes(tempDs);
      if(m_SceneIO.IsNull())
      {
        m_SceneIO = mitk::SceneIO::New();
      }
      save = m_SceneIO->SaveScene( sceneNodes.GetPointer(), tempDs, theFile );
  }
  if( save )
  {
      long int currentModifiedTime = itksys::SystemTools::ModifiedTime( theFile.c_str() );
      m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
  }

  return save;
}

bool mitk::PersistenceService::Load(const std::string& fileName, bool enforceReload)
{
  this->Initialize();
  bool load = false;

  std::string theFile = fileName;
  if(theFile.empty())
      theFile = PersistenceService::GetDefaultPersistenceFile();

  MITK_DEBUG << "Load persistence data from file: " << theFile;

  if( !itksys::SystemTools::FileExists(theFile.c_str()) )
      return false;

  bool xmlFile = false;
  if( itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml" )
      xmlFile = true;

  if( enforceReload == false )
  {
      bool loadTheFile = true;
      std::map<std::string, long int>::iterator it = m_FileNamesToModifiedTimes.find( theFile );

      long int currentModifiedTime = itksys::SystemTools::ModifiedTime( theFile.c_str() );
      if( it != m_FileNamesToModifiedTimes.end() )
      {
          long int knownModifiedTime = (*it).second;
          if( knownModifiedTime >= currentModifiedTime )
          {
              loadTheFile = false;
          }
      }
      if( loadTheFile )
          m_FileNamesToModifiedTimes[theFile] = currentModifiedTime;
      else
          return true;
  }

  if( xmlFile )
  {
      load = m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists);
  }
  else
  {
    if(m_SceneIO.IsNull())
    {
      m_SceneIO = mitk::SceneIO::New();
    }
      DataStorage::Pointer ds = m_SceneIO->LoadScene( theFile );
      load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) && (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty());
      if( load )
      {
          this->RestorePropertyListsFromPersistentDataNodes( ds );
      }
  }
  if( !load )
  {
      MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed";
      return load;
  }

  return load;
}

void mitk::PersistenceService::SetAutoLoadAndSave(bool autoLoadAndSave)
{
  this->Initialize();
  m_AutoLoadAndSave = autoLoadAndSave;
  //std::string id = PERSISTENCE_PROPERTYLIST_NAME; //see bug 17729
  std::string id = GetPersistencePropertyListName();
  mitk::PropertyList::Pointer propList = this->GetPropertyList( id );
  propList->Set("m_AutoLoadAndSave", m_AutoLoadAndSave);
  this->Save();
}

void mitk::PersistenceService::AddPropertyListReplacedObserver(PropertyListReplacedObserver* observer)
{
  this->Initialize();
  m_PropertyListReplacedObserver.insert( observer );
}

void mitk::PersistenceService::RemovePropertyListReplacedObserver(PropertyListReplacedObserver* observer)
{
  this->Initialize();
  m_PropertyListReplacedObserver.erase( observer );
}

void mitk::PersistenceService::LoadModule()
{
    MITK_DEBUG << "Persistence Module loaded.";
}

us::ModuleContext* mitk::PersistenceService::GetModuleContext()
{
  return us::GetModuleContext();
}

std::string mitk::PersistenceService::GetPersistenceNodePropertyName()
{
  this->Initialize();
  //return PERSISTENCE_PROPERTY_NAME; //see bug 17729
  return GetPersistencePropertyName();
}
mitk::DataStorage::SetOfObjects::Pointer mitk::PersistenceService::GetDataNodes(mitk::DataStorage* ds)
{
  this->Initialize();
  DataStorage::SetOfObjects::Pointer set = DataStorage::SetOfObjects::New();

  std::map<std::string, mitk::PropertyList::Pointer>::const_iterator it = m_PropertyLists.begin();
  while( it != m_PropertyLists.end() )
  {
      mitk::DataNode::Pointer node = mitk::DataNode::New();
      const std::string& name = (*it).first;

      this->ClonePropertyList( (*it).second, node->GetPropertyList() );


      node->SetName( name );
{'fraction_non_alphanumeric': 0.14976805831676607, 'fraction_numerical': 0.0017671747294013696, 'mean_word_length': 4.109762979683973, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 24}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4618018', 'n_tokens_mistral': 5692, 'n_tokens_neox': 5569, 'n_words': 1003}