diff --git a/Core/Code/Interfaces/mitkIPersistenceService.h b/Core/Code/Interfaces/mitkIPersistenceService.h index e320113e68..0e79bcaccc 100644 --- a/Core/Code/Interfaces/mitkIPersistenceService.h +++ b/Core/Code/Interfaces/mitkIPersistenceService.h @@ -1,341 +1,344 @@ /*=================================================================== 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. ===================================================================*/ #ifndef mitkIPersistenceService_h #define mitkIPersistenceService_h // mitk #include "mitkPropertyListReplacedObserver.h" #include "usServiceReference.h" #include "usModuleContext.h" #include "usGetModuleContext.h" //for microservices #include #include "mitkDataStorage.h" namespace mitk { /// /// The central service for the persistence module /// Basic idea is to create PropertyLists with a unique id using AddPropertyList(). A consumer /// of this interface can write arbitrary information into this propertylist /// Calling Save() and Load() will cause the Service to save and load the current set of propertlists from /// a file in the user directory. /// Using SetAutoLoadAndSave(true) will cause the service to load/save the property lists at application /// start/stop. /// Moreover, depending on the backend type, the service is connected to the SceneSerialization module, i.e. /// the user will be asked whether to save/load the propertlists in/from the current ".mitk" file that is selected /// by the user. /// class MITK_CORE_EXPORT IPersistenceService { public: /// /// If PropertyList with the given id exists, returns it. Otherwise creates a new one and returns it. /// If id is empty a UUID will be created and set on the variable /// If existed was passed, it is true if the PropertyList with that id existed, false otherwise /// \return a valid PropertyList with a StringProperty "Id" containing the passed id /// virtual mitk::PropertyList::Pointer GetPropertyList( std::string& id, bool* existed=0 ) = 0; /// + /// removes the PropertyList with the given id + /// \return true if PropertyList existed and could be removed, false otherwise + /// + virtual bool RemovePropertyList( std::string& id ) = 0; + /// /// Get the default name of the PersistenceFile (the one that is loaded at startup) /// virtual std::string GetDefaultPersistenceFile() const = 0; /// /// \return The name of the Bool Property that specifies whether a DataNode is a Node carrying Persistence PropertyLists /// virtual std::string GetPersistenceNodePropertyName() const = 0; /// /// Creates a vector of DataNodes that contain all PropertyLists. Additionally, the DataNodes /// will have the property name set to the PropertyList's id and a BoolProperty equal to GetPersistenceNodePropertyName() set to true /// \return vector of DataNodes with the described attributes /// virtual DataStorage::SetOfObjects::Pointer GetDataNodes() const = 0; /// /// Searches storage for persistent DataNodes, extracts and inserts the appended property lists to this service /// \return true if at least one node was found from which a PropertyList could be restored /// virtual bool RestorePropertyListsFromPersistentDataNodes(DataStorage* storage) = 0; /// /// Save the current PropertyLists to fileName. If fileName is empty, a special file in the users home directory will be used. /// if appendchanges is true, the file will not replaced but first loaded, then overwritten and then replaced /// \return false if an error occured (cannot write to file), true otherwise /// virtual bool Save(const std::string& fileName="", bool appendChanges=false) = 0; /// /// Load PropertyLists from fileName. If fileName is empty, a special file in the users home directory will be used. /// If enforeReload is false, the service will take care of modified time flags, i.e. it will not load a file /// that was loaded before and did not change in the meantime or that was modified by the service itself /// *ATTENTION*: If there are PropertyLists with the same id contained in the file, existing PropertyLists will be overwritten! /// \see AddPropertyListReplacedObserver() /// \return false if an error occured (cannot load from file), true otherwise /// virtual bool Load(const std::string& fileName="", bool enforeReload=true) = 0; /// /// Using SetAutoLoadAndSave(true) will cause the service to load/save the property lists at application /// start/stop. /// virtual void SetAutoLoadAndSave(bool autoLoadAndSave) = 0; /// /// \return whether AutoLoading is activated or not /// virtual bool GetAutoLoadAndSave() const = 0; /// /// adds a observer which is informed if a propertyList gets replaced during a Load() procedure /// virtual void AddPropertyListReplacedObserver( PropertyListReplacedObserver* observer ) = 0; /// /// removes a specific observer /// virtual void RemovePropertyListReplacedObserver( PropertyListReplacedObserver* observer ) = 0; /// /// nothing to do here /// virtual ~IPersistenceService(); }; } /// MACROS FOR AUTOMATIC SAVE FUNCTION #define PERSISTENCE_GET_MODULE_CONTEXT_FUNCTION\ us::GetModuleContext() #define PERSISTENCE_GET_SERVICE_MACRO\ mitk::IPersistenceService* persistenceService = 0;\ us::ModuleContext* context = PERSISTENCE_GET_MODULE_CONTEXT_FUNCTION;\ if( context )\ {\ us::ServiceReference persistenceServiceRef = context->GetServiceReference();\ if( persistenceServiceRef )\ {\ persistenceService\ = dynamic_cast ( context->GetService(persistenceServiceRef) );\ }\ } #define PERSISTENCE_GET_SERVICE_METHOD_MACRO\ mitk::IPersistenceService* GetPeristenceService() const\ {\ static mitk::IPersistenceService* staticPersistenceService = 0;\ if( staticPersistenceService == 0 )\ {\ PERSISTENCE_GET_SERVICE_MACRO\ staticPersistenceService = persistenceService;\ }\ return staticPersistenceService;\ } #define PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ public:\ - bool Save(const std::string& fileName="")\ + bool Save(const std::string& fileName="", bool appendChanges=false)\ {\ mitk::IPersistenceService* persistenceService = this->GetPeristenceService();\ bool noError = persistenceService != 0;\ if( noError )\ this->ToPropertyList();\ if(noError)\ - noError = persistenceService->Save(fileName);\ + noError = persistenceService->Save(fileName, appendChanges);\ return noError;\ }\ - bool Load(const std::string& fileName="")\ + bool Load(const std::string& fileName="", bool enforeReload=true)\ {\ mitk::IPersistenceService* persistenceService = this->GetPeristenceService();\ - bool noError = persistenceService != 0 && persistenceService->Load(fileName);\ + bool noError = persistenceService != 0 && persistenceService->Load(fileName, enforeReload);\ if( noError )\ {\ this->FromPropertyList();\ }\ return noError;\ }\ void ToPropertyList()\ {\ mitk::IPersistenceService* persistenceService = this->GetPeristenceService();\ this->InitializePropertyListReplacedObserver(persistenceService);\ if( !persistenceService )\ return;\ - mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(ID_MEMBER_NAME);\ - propList->Set(#ID_MEMBER_NAME, ID_MEMBER_NAME); + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(ID_MEMBER_NAME); #define PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ }\ void FromPropertyList()\ {\ mitk::IPersistenceService* persistenceService = this->GetPeristenceService();\ this->InitializePropertyListReplacedObserver(persistenceService);\ if( !persistenceService )\ return;\ - mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(ID_MEMBER_NAME);\ - propList->Get(#ID_MEMBER_NAME, ID_MEMBER_NAME); + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(ID_MEMBER_NAME); #define PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME)\ }\ std::string GetId() const\ {\ return ID_MEMBER_NAME;\ }\ private:\ PERSISTENCE_GET_SERVICE_METHOD_MACRO\ struct MyPropertyListReplacedObserver: public mitk::PropertyListReplacedObserver\ {\ MyPropertyListReplacedObserver()\ : m_##THE_CLASS_NAME(0), m_PersistenceService(0)\ {\ }\ ~MyPropertyListReplacedObserver()\ {\ if( m_PersistenceService )\ m_PersistenceService->RemovePropertyListReplacedObserver(this);\ }\ void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList )\ {\ if( m_##THE_CLASS_NAME && m_##THE_CLASS_NAME->GetId() == id )\ m_##THE_CLASS_NAME->FromPropertyList();\ }\ void Initialize( THE_CLASS_NAME##* _##THE_CLASS_NAME, mitk::IPersistenceService* persistenceService )\ {\ m_##THE_CLASS_NAME = _##THE_CLASS_NAME;\ m_PersistenceService = persistenceService;\ if( m_PersistenceService )\ m_PersistenceService->AddPropertyListReplacedObserver(this);\ }\ private:\ THE_CLASS_NAME##* m_##THE_CLASS_NAME;\ mitk::IPersistenceService* m_PersistenceService;\ };\ MyPropertyListReplacedObserver m_MyPropertyListReplacedObserver;\ void InitializePropertyListReplacedObserver(mitk::IPersistenceService* persistenceService)\ {\ static bool observerInitialized = false;\ if( observerInitialized == false && persistenceService )\ {\ m_MyPropertyListReplacedObserver.Initialize( this, persistenceService );\ observerInitialized = true;\ }\ } #define PERSISTENCE_CREATE(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE2(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE3(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE4(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME, PARAM4_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Set( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Get( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE5(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME, PARAM4_MEMBER_NAME, PARAM5_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Set( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Set( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Get( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Get( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE6(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME, PARAM4_MEMBER_NAME, PARAM5_MEMBER_NAME, PARAM6_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Set( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Set( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Set( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Get( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Get( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Get( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE7(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME, PARAM4_MEMBER_NAME, PARAM5_MEMBER_NAME, PARAM6_MEMBER_NAME, PARAM7_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Set( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Set( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Set( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ propList->Set( #PARAM7_MEMBER_NAME, PARAM7_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Get( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Get( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Get( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ propList->Get( #PARAM7_MEMBER_NAME, PARAM7_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) #define PERSISTENCE_CREATE8(THE_CLASS_NAME, ID_MEMBER_NAME, PARAM_MEMBER_NAME, PARAM2_MEMBER_NAME, PARAM3_MEMBER_NAME, PARAM4_MEMBER_NAME, PARAM5_MEMBER_NAME, PARAM6_MEMBER_NAME, PARAM7_MEMBER_NAME, PARAM8_MEMBER_NAME)\ PERSISTENCE_MACRO_START_PART(ID_MEMBER_NAME)\ propList->Set( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Set( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Set( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Set( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Set( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Set( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ propList->Set( #PARAM7_MEMBER_NAME, PARAM7_MEMBER_NAME );\ propList->Set( #PARAM8_MEMBER_NAME, PARAM8_MEMBER_NAME );\ PERSISTENCE_MACRO_MIDDLE_PART(ID_MEMBER_NAME)\ propList->Get( #PARAM_MEMBER_NAME, PARAM_MEMBER_NAME );\ propList->Get( #PARAM2_MEMBER_NAME, PARAM2_MEMBER_NAME );\ propList->Get( #PARAM3_MEMBER_NAME, PARAM3_MEMBER_NAME );\ propList->Get( #PARAM4_MEMBER_NAME, PARAM4_MEMBER_NAME );\ propList->Get( #PARAM5_MEMBER_NAME, PARAM5_MEMBER_NAME );\ propList->Get( #PARAM6_MEMBER_NAME, PARAM6_MEMBER_NAME );\ propList->Get( #PARAM7_MEMBER_NAME, PARAM7_MEMBER_NAME );\ propList->Get( #PARAM8_MEMBER_NAME, PARAM8_MEMBER_NAME );\ PERSISTENCE_MACRO_END_PART(THE_CLASS_NAME, ID_MEMBER_NAME) US_DECLARE_SERVICE_INTERFACE(mitk::IPersistenceService, "org.mitk.services.IPersistenceService") #endif diff --git a/Modules/Persistence/Testing/mitkPersistenceTest.cpp b/Modules/Persistence/Testing/mitkPersistenceTest.cpp index c304c4b635..1de4ea26c9 100644 --- a/Modules/Persistence/Testing/mitkPersistenceTest.cpp +++ b/Modules/Persistence/Testing/mitkPersistenceTest.cpp @@ -1,109 +1,164 @@ /*=================================================================== 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 #include #include #include #include #include #include #include "Poco\File.h" struct PersistenceTestClass { PersistenceTestClass() : id(""), param1(1), param2(2), param3(false) { } std::string id; int param1; double param2; bool param3; PERSISTENCE_CREATE3(PersistenceTestClass, id, param1, param2, param3) }; - -struct PersistenceTestClass2 -{ -}; - struct TestPropertyListReplacedObserver: public mitk::PropertyListReplacedObserver { TestPropertyListReplacedObserver(): counter(0) {} virtual void BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) { - counter++; + if( id == m_Id ) + counter++; } virtual void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) { - counter++; + if( id == m_Id ) + counter++; } int counter; + std::string m_Id; }; +std::string testClassId = "testClass"; +int param1 = 100; +double param2 = 201.56; +bool param3 = true; + +void testParams( const PersistenceTestClass& testClass, const std::string& testClassName ) +{ + MITK_INFO << "Testing parameters of " << testClassName; + MITK_TEST_CONDITION( testClass.id == testClassId, "testClass.id (" << testClass.id << ") != testClassId (" << testClassId << ")" ); + MITK_TEST_CONDITION( testClass.param1 == param1, "testClass.param1 (" << testClass.param1 << ") != param1 (" << param1 << ")" ); + MITK_TEST_CONDITION( testClass.param2 == param2, "testClass.param2 (" << testClass.param2 << ") != param2 (" << param2 << ")" ); + MITK_TEST_CONDITION( testClass.param3 == param3, "testClass.param3 (" << testClass.param3 << ") != param3 (" << param3 << ")" ); +} + int mitkPersistenceTest(int /*argc*/, char* /*argv*/[]) { + MITK_TEST_BEGIN("PersistenceTest") // dummy load of SceneIO, otherwise PersistenceService won't be available mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); - Poco::File testTempFile("Test.mitk"); + MITK_INFO << "Testing availability of the PersistenceService."; + PERSISTENCE_GET_SERVICE_MACRO + MITK_TEST_CONDITION_REQUIRED(persistenceService, "IPersistenceService available") + + MITK_INFO << "Initialize testable parameter values."; + + Poco::File defaultPersistenceFile(persistenceService->GetDefaultPersistenceFile()); + if( defaultPersistenceFile.exists() && persistenceService->GetAutoLoadAndSave() ) + { + MITK_INFO << "Testing auto load/save of the PersistenceService."; + + PersistenceTestClass autoLoadTestClass; + autoLoadTestClass.id = testClassId; + autoLoadTestClass.FromPropertyList(); + + testParams( autoLoadTestClass, "autoLoadTestClass" ); + } + + MITK_INFO << "Removing left-over test files."; + Poco::File testTempFile("PersistenceTestFile.mitk"); if( testTempFile.exists() ) testTempFile.remove(false); - MITK_TEST_BEGIN("PersistenceTest") + Poco::File testXmlTempFile("PersistenceTestFile.xml"); + if( testXmlTempFile.exists() ) + testXmlTempFile.remove(false); + + MITK_INFO << "Testing standard write to scene file/xml file."; PersistenceTestClass testClass; - testClass.id = "testClass"; - testClass.param1 = 100; - testClass.param2 = 200.56; - testClass.param3 = true; - MITK_TEST_CONDITION_REQUIRED( testClass.Save(), "testClass.Save()"); + testClass.id = testClassId; + testClass.param1 = param1; + testClass.param2 = param2; + testClass.param3 = param3; MITK_TEST_CONDITION_REQUIRED( testClass.Save(testTempFile.path()), "testClass.Save(testTempFile.path())"); + MITK_TEST_CONDITION_REQUIRED( testClass.Save(testXmlTempFile.path()), "testClass.Save(testTempFile.path())"); + MITK_INFO << "Testing read from scene file."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); PersistenceTestClass testClass2; - testClass2.id = "testClass"; - MITK_TEST_CONDITION_REQUIRED( testClass2.Load(), "testClass2.Load()"); + testClass2.id = testClassId; + MITK_TEST_CONDITION_REQUIRED( testClass2.Load(testTempFile.path()), "testClass2.Load(testTempFile.path())"); - MITK_TEST_CONDITION_REQUIRED( testClass.param1 == testClass2.param1, "testClass.param1 == testClass2.param1" ); - MITK_TEST_CONDITION_REQUIRED( testClass.param2 == testClass2.param2, "testClass.param2 == testClass2.param2" ); - MITK_TEST_CONDITION_REQUIRED( testClass.param3 == testClass2.param3, "testClass.param3 == testClass2.param3" ); + testParams( testClass2, "testClass2" ); + MITK_INFO << "Testing read from xml file."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); PersistenceTestClass testClass3; - testClass3.id = "testClass"; - MITK_TEST_CONDITION_REQUIRED( testClass3.Load(testTempFile.path()), "testClass3.Load(testTempFile.path())"); + testClass3.id = testClassId; + MITK_TEST_CONDITION_REQUIRED( testClass3.Load(testXmlTempFile.path()), "testClass3.Load(testXmlTempFile.path())"); - MITK_TEST_CONDITION_REQUIRED( testClass.param1 == testClass3.param1, "testClass.param1 == testClass3.param1" ); - MITK_TEST_CONDITION_REQUIRED( testClass.param2 == testClass3.param2, "testClass.param2 == testClass3.param2" ); - MITK_TEST_CONDITION_REQUIRED( testClass.param3 == testClass3.param3, "testClass.param3 == testClass3.param3" ); + testParams( testClass3, "testClass3" ); - TestPropertyListReplacedObserver testObserver; + MITK_INFO << "Testing appendChanges functionality with scene load/write."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testTempFile.path(), true), "persistenceService->Save(testTempFile.path())"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testTempFile.path()), "persistenceService->Load(testTempFile.path())"); - PERSISTENCE_GET_SERVICE_MACRO + PersistenceTestClass testClass4; + testClass4.id = testClassId; + testClass4.FromPropertyList(); + testParams( testClass4, "testClass4" ); - MITK_TEST_CONDITION_REQUIRED(persistenceService, "IPersistenceService available") + MITK_INFO << "Testing appendChanges functionality with xml load/write."; + MITK_TEST_CONDITION_REQUIRED( persistenceService->RemovePropertyList(testClassId), "persistenceService->RemovePropertyList(testClassId)"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Save(testXmlTempFile.path(), true), "persistenceService->Save(testXmlTempFile.path())"); + MITK_TEST_CONDITION_REQUIRED( persistenceService->Load(testXmlTempFile.path()), "persistenceService->Load(testXmlTempFile.path())"); + + PersistenceTestClass testClass5; + testClass5.id = testClassId; + testClass5.FromPropertyList(); + testParams( testClass5, "testClass5" ); + MITK_INFO << "Testing observer functionality."; + TestPropertyListReplacedObserver testObserver; + testObserver.m_Id = testClassId; persistenceService->AddPropertyListReplacedObserver( &testObserver ); persistenceService->Load(); + MITK_TEST_CONDITION( testObserver.counter == 2, "testObserver.counter == 2" ); - MITK_TEST_CONDITION_REQUIRED( testObserver.counter == 4, "testObserver.counter == 4" ); - + MITK_INFO << "Cleaning test files."; + if( testXmlTempFile.exists() ) + testXmlTempFile.remove(false); if( testTempFile.exists() ) - testTempFile.remove(false); + testTempFile.remove(false); MITK_TEST_END() } diff --git a/Modules/Persistence/files.cmake b/Modules/Persistence/files.cmake index e93bb8fe5a..9604345c04 100644 --- a/Modules/Persistence/files.cmake +++ b/Modules/Persistence/files.cmake @@ -1,4 +1,5 @@ set(CPP_FILES mitkPersistenceService.cpp mitkPersistenceActivator.cpp +mitkPropertyListsXmlFileReaderAndWriter.cpp ) diff --git a/Modules/Persistence/mitkPersistenceService.cpp b/Modules/Persistence/mitkPersistenceService.cpp index fc7ff40cda..49af034883 100644 --- a/Modules/Persistence/mitkPersistenceService.cpp +++ b/Modules/Persistence/mitkPersistenceService.cpp @@ -1,280 +1,323 @@ /*=================================================================== 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 const std::string mitk::PersistenceService::PERSISTENCE_PROPERTY_NAME("PersistenceNode"); const std::string mitk::PersistenceService::PERSISTENCE_PROPERTYLIST_NAME("PersistenceService"); -const std::string mitk::PersistenceService::ID_PROPERTY_NAME("Id"); +const std::string mitk::PersistenceService::ID_PROPERTY_NAME("id"); mitk::PersistenceService::PersistenceService() - : m_AutoLoadAndSave( true ), m_SceneIO( SceneIO::New() ) +: m_AutoLoadAndSave( true ), m_SceneIO( SceneIO::New() ), m_PropertyListsXmlFileReaderAndWriter( PropertyListsXmlFileReaderAndWriter::New() ) { } void mitk::PersistenceService::Clear() { m_PropertyLists.clear(); m_FileNamesToModifiedTimes.clear(); } mitk::PersistenceService::~PersistenceService() { MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService"; } std::string mitk::PersistenceService::GetDefaultPersistenceFile() const { std::string file = "PersistentData.mitk"; return file; } mitk::PropertyList::Pointer mitk::PersistenceService::GetPropertyList( std::string& id, bool* existed ) { mitk::PropertyList::Pointer propList; if( id.empty() ) { UIDGenerator uidGen; id = uidGen.GetUID(); } std::map::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) { bool save = false; std::string theFile = fileName; if(theFile.empty()) theFile = PersistenceService::GetDefaultPersistenceFile(); + bool xmlFile = false; + if( itksys::SystemTools::GetFilenameLastExtension(theFile.c_str()) == ".xml" ) + xmlFile = true; + mitk::DataStorage::Pointer tempDs; - if(appendChanges) + if(appendChanges && xmlFile == false) { - if( !itksys::SystemTools::FileExists(theFile.c_str()) ) - return false; + if( itksys::SystemTools::FileExists(theFile.c_str()) ) + { - DataStorage::Pointer ds = m_SceneIO->LoadScene( theFile ); - bool load = (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedNodes()->size() == 0) && (m_SceneIO->GetFailedNodes() == 0 || m_SceneIO->GetFailedProperties()->IsEmpty()); - if( !load ) - return false; + 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; - 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; + } + } DataStorage::SetOfObjects::Pointer rs = DataStorage::SetOfObjects::New(); - save = m_SceneIO->SaveScene( rs.GetPointer(), tempDs, theFile ); + if( xmlFile ) + { + save = m_PropertyListsXmlFileReaderAndWriter->WriteLists(theFile, m_PropertyLists); + } + else + { + save = m_SceneIO->SaveScene( rs.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) { bool load = false; std::string theFile = fileName; if(theFile.empty()) theFile = PersistenceService::GetDefaultPersistenceFile(); 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::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; } - 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( xmlFile ) + { + load = m_PropertyListsXmlFileReaderAndWriter->ReadLists(theFile, m_PropertyLists); + } + else + { + 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 ) { MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed"; return load; } return load; } void mitk::PersistenceService::SetAutoLoadAndSave(bool autoLoadAndSave) { m_AutoLoadAndSave = autoLoadAndSave; std::string id = PERSISTENCE_PROPERTYLIST_NAME; mitk::PropertyList::Pointer propList = this->GetPropertyList( id ); propList->Set("m_AutoLoadAndSave", m_AutoLoadAndSave); this->Save(); } void mitk::PersistenceService::AddPropertyListReplacedObserver(PropertyListReplacedObserver* observer) { m_PropertyListReplacedObserver.insert( observer ); } void mitk::PersistenceService::RemovePropertyListReplacedObserver(PropertyListReplacedObserver* observer) { m_PropertyListReplacedObserver.erase( observer ); } us::ModuleContext* mitk::PersistenceService::GetModuleContext() { return us::GetModuleContext(); } std::string mitk::PersistenceService::GetPersistenceNodePropertyName() const { return PERSISTENCE_PROPERTY_NAME; } mitk::DataStorage::SetOfObjects::Pointer mitk::PersistenceService::GetDataNodes() const { DataStorage::SetOfObjects::Pointer set = DataStorage::SetOfObjects::New(); std::map::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->SetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str(), true ); node->SetName( name ); node->SetStringProperty(ID_PROPERTY_NAME.c_str(), name.c_str() ); set->push_back( node ); ++it; } return set; } bool mitk::PersistenceService::RestorePropertyListsFromPersistentDataNodes( DataStorage* storage ) { bool oneFound = false; DataStorage::SetOfObjects::ConstPointer allNodes = storage->GetAll(); for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = allNodes->begin(); sourceIter != allNodes->end(); ++sourceIter ) { mitk::DataNode* node = *sourceIter; bool isPersistenceNode = false; node->GetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str(), isPersistenceNode ); if( isPersistenceNode ) { oneFound = true; MITK_DEBUG("mitk::PersistenceService") << "isPersistenceNode was true"; std::string name = node->GetName(); bool existed = false; mitk::PropertyList::Pointer propList = this->GetPropertyList( name, &existed ); if( existed ) { MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values"; std::set::iterator it = m_PropertyListReplacedObserver.begin(); while( it != m_PropertyListReplacedObserver.end() ) { (*it)->BeforePropertyListReplaced( name, propList ); ++it; } } // if( existed ) MITK_DEBUG("mitk::PersistenceService") << "replacing values"; this->ClonePropertyList( node->GetPropertyList(), propList ); propList->SetStringProperty(ID_PROPERTY_NAME.c_str(), name.c_str()); if( existed ) { MITK_DEBUG("mitk::PersistenceService") << "calling replace observer before replacing values"; std::set::iterator it = m_PropertyListReplacedObserver.begin(); while( it != m_PropertyListReplacedObserver.end() ) { (*it)->AfterPropertyListReplaced( name, propList ); ++it; } } // if( existed ) } // if( isPersistenceNode ) } // for ( mitk::DataStorage::SetOfObjects::const_iterator sourceIter = allNodes->begin(); ... return oneFound; } bool mitk::PersistenceService::GetAutoLoadAndSave() const { return m_AutoLoadAndSave; } + +bool mitk::PersistenceService::RemovePropertyList( std::string& id ) +{ + std::map::iterator it = m_PropertyLists.find( id ); + if( it != m_PropertyLists.end() ) + { + m_PropertyLists.erase(it); + return true; + } + return false; +} diff --git a/Modules/Persistence/mitkPersistenceService.h b/Modules/Persistence/mitkPersistenceService.h index 705f41f9d0..74caa8ba22 100644 --- a/Modules/Persistence/mitkPersistenceService.h +++ b/Modules/Persistence/mitkPersistenceService.h @@ -1,72 +1,76 @@ /*=================================================================== 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. ===================================================================*/ #ifndef mitkPersistenceService_h #define mitkPersistenceService_h #include "mitkIPersistenceService.h" +#include "mitkPropertyListsXmlFileReaderAndWriter.h" #include #include "mitkSceneIO.h" namespace mitk { /// /// implementation of the IPersistenceService /// \see IPersistenceService class PersistenceService: public itk::LightObject, public mitk::IPersistenceService { public: static const std::string PERSISTENCE_PROPERTY_NAME; static const std::string PERSISTENCE_PROPERTYLIST_NAME; static const std::string ID_PROPERTY_NAME; static us::ModuleContext* GetModuleContext(); PersistenceService(); ~PersistenceService(); std::string GetDefaultPersistenceFile() const; mitk::PropertyList::Pointer GetPropertyList( std::string& id, bool* existed=0 ); + bool RemovePropertyList( std::string& id ); + std::string GetPersistenceNodePropertyName() const; DataStorage::SetOfObjects::Pointer GetDataNodes() const; bool Save(const std::string& fileName="", bool appendChanges=false); bool Load(const std::string& fileName="", bool enforeReload=true); void SetAutoLoadAndSave(bool autoLoadAndSave); bool GetAutoLoadAndSave() const; void AddPropertyListReplacedObserver( PropertyListReplacedObserver* observer ); void RemovePropertyListReplacedObserver( PropertyListReplacedObserver* observer ); bool RestorePropertyListsFromPersistentDataNodes(DataStorage* storage); void Clear(); private: void ClonePropertyList( mitk::PropertyList* from, mitk::PropertyList* to ) const; std::map m_PropertyLists; bool m_AutoLoadAndSave; std::set m_PropertyListReplacedObserver; SceneIO::Pointer m_SceneIO; + PropertyListsXmlFileReaderAndWriter::Pointer m_PropertyListsXmlFileReaderAndWriter; std::map m_FileNamesToModifiedTimes; }; } #endif diff --git a/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.cpp b/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.cpp new file mode 100644 index 0000000000..11abb78043 --- /dev/null +++ b/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.cpp @@ -0,0 +1,254 @@ +/*=================================================================== + +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 "mitkPropertyListsXmlFileReaderAndWriter.h" +#include "mitkStandaloneDataStorage.h" +#include "mitkProperties.h" +#include +#include + +namespace mitk +{ + +bool PropertyListsXmlFileReaderAndWriter::PropertyFromXmlElem(std::string& name, mitk::BaseProperty::Pointer& prop, TiXmlElement* elem) const +{ + if(!elem) + { + return false; + } + + bool readOp = false; + std::string type = ""; + readOp = elem->QueryStringAttribute("type", &type) == TIXML_SUCCESS; + if( readOp ) + readOp = elem->QueryStringAttribute("name", &name) == TIXML_SUCCESS; + else + MITK_WARN << "type" << " attribute not found in a property"; + + if( readOp ) + { + if( type == "BoolProperty" ) + { + int val = 0; + readOp = elem->QueryIntAttribute("value", &val) == TIXML_SUCCESS; + if( readOp ) + { + prop = mitk::BoolProperty::New(val==1?true: false); + } + } + else if( type == "StringProperty" ) + { + std::string val = ""; + readOp = elem->QueryStringAttribute("value", &val) == TIXML_SUCCESS; + if( readOp ) + { + prop = mitk::StringProperty::New(val); + } + } + else if( type == "IntProperty" ) + { + int val = 0; + readOp = elem->QueryIntAttribute("value", &val) == TIXML_SUCCESS; + if( readOp ) + { + prop = mitk::IntProperty::New(val); + } + } + else if( type == "DoubleProperty" ) + { + double val = 0; + readOp = elem->QueryDoubleAttribute("value", &val) == TIXML_SUCCESS; + if( readOp ) + { + prop = mitk::DoubleProperty::New(val); + } + + } + else if( type == "FloatProperty" ) + { + float val = 0; + readOp = elem->QueryFloatAttribute("value", &val) == TIXML_SUCCESS; + if( readOp ) + { + prop = mitk::FloatProperty::New(val); + } + } + else + { + readOp = false; + MITK_WARN << "type" << " attribute unknown. Only BoolProperty, StringProperty, IntProperty, DoubleProperty or FloatProperty allowed."; + } + } + else + MITK_WARN << "name" << " attribute not found in a property"; + + if( !readOp ) + MITK_WARN << "value" << " attribute not found in a property"; + + return readOp; + +} +bool PropertyListsXmlFileReaderAndWriter::PropertyToXmlElem(const std::string& name, const mitk::BaseProperty* prop, TiXmlElement* elem) const +{ + if(!prop || !elem) + { + return false; + } + + const mitk::IntProperty* intProp = 0; + const mitk::FloatProperty* floatProp = 0; + const mitk::DoubleProperty* doubleProp = 0; + const mitk::BoolProperty* boolProp = 0; + const mitk::StringProperty* stringProp = 0; + bool writeOp = true; + + if( (boolProp = dynamic_cast( prop ) ) ) + { + elem->SetAttribute("name", name); + elem->SetAttribute("value", boolProp->GetValue()? 1: 0); + elem->SetAttribute("type", "BoolProperty"); + } + else if( (stringProp = dynamic_cast( prop ) ) ) + { + elem->SetAttribute("name", name); + elem->SetAttribute("value", stringProp->GetValue()); + elem->SetAttribute("type", "StringProperty"); + } + else if( (intProp = dynamic_cast( prop ) ) ) + { + elem->SetAttribute("name", name); + elem->SetAttribute("value", intProp->GetValue()); + elem->SetAttribute("type", "IntProperty"); + } + else if( (doubleProp = dynamic_cast( prop ) ) ) + { + elem->SetAttribute("name", name); + elem->SetDoubleAttribute("value", doubleProp->GetValue()); + elem->SetAttribute("type", "DoubleProperty"); + } + else if( (floatProp = dynamic_cast( prop ) ) ) + { + elem->SetAttribute("name", name); + elem->SetDoubleAttribute("value", static_cast( floatProp->GetValue() ) ); + elem->SetAttribute("type", "FloatProperty"); + } + else + { + MITK_WARN("PropertyListImportFromXmlFile") << "Base property " << name << " is unknown"; + writeOp = false; + } + return writeOp; +} +bool PropertyListsXmlFileReaderAndWriter::WriteLists( const std::string& fileName, const std::map& _PropertyLists ) const +{ + + TiXmlDocument doc; + + TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); + doc.LinkEndChild( decl ); + // create root + TiXmlElement* propertyListsElem = new TiXmlElement( "PropertyLists" ); + + bool allPropsConverted = true; + std::map::const_iterator it = _PropertyLists.begin(); + while( it != _PropertyLists.end() ) + { + const std::string& id = (*it).first; + const PropertyList* propList = (*it).second; + TiXmlElement* propertyListElem = new TiXmlElement( "PropertyList" ); + propertyListElem->SetAttribute("id", id); + + const std::map< std::string, BaseProperty::Pointer>* propMap = propList->GetMap(); + std::map< std::string, BaseProperty::Pointer>::const_iterator propMapIt = propMap->begin(); + while( propMapIt != propMap->end() ) + { + const std::string& propName = (*propMapIt).first; + const BaseProperty* prop = (*propMapIt).second; + TiXmlElement* propertyElem = new TiXmlElement( "Property" ); + + if( !this->PropertyToXmlElem(propName, prop, propertyElem) ) + allPropsConverted = false; + + propertyListElem->LinkEndChild(propertyElem); + ++propMapIt; + } + + propertyListsElem->LinkEndChild(propertyListElem); + ++it; + } + + doc.LinkEndChild( propertyListsElem ); + + return ( allPropsConverted && doc.SaveFile( fileName.c_str() ) ); +} +bool PropertyListsXmlFileReaderAndWriter::ReadLists( const std::string& fileName, std::map& _PropertyLists ) const +{ + // reread + TiXmlDocument doc( fileName ); + doc.LoadFile(); + + TiXmlHandle docHandle( &doc ); + TiXmlElement* elem = docHandle.FirstChildElement( "PropertyLists" ).FirstChildElement( "PropertyList" ).ToElement(); + + if(!elem) + { + MITK_WARN("PropertyListFromXml") << "Cannot find a PropertyList element (inside a PropertyLists element)"; + return false; + } + + bool opRead = false; + while(elem) + { + std::string propListId; + opRead = elem->QueryStringAttribute( "id", &propListId ) == TIXML_SUCCESS; + if( !opRead ) + break; + + mitk::PropertyList::Pointer propList = mitk::PropertyList::New(); + + TiXmlElement* propElem = elem->FirstChildElement("Property"); + + while(propElem) + { + std::string name; + mitk::BaseProperty::Pointer prop; + opRead = this->PropertyFromXmlElem( name, prop, propElem ); + if(!opRead) + break; + propList->SetProperty( name, prop ); + propElem = propElem->NextSiblingElement( "Property" ); + } + + if( !opRead ) + break; + _PropertyLists[propListId] = propList; + elem = elem->NextSiblingElement( "PropertyList" ); + } + + return opRead; +} + +PropertyListsXmlFileReaderAndWriter::PropertyListsXmlFileReaderAndWriter() +{ + +} + +PropertyListsXmlFileReaderAndWriter::~PropertyListsXmlFileReaderAndWriter() +{ + +} + +} \ No newline at end of file diff --git a/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.h b/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.h new file mode 100644 index 0000000000..79ecc01489 --- /dev/null +++ b/Modules/Persistence/mitkPropertyListsXmlFileReaderAndWriter.h @@ -0,0 +1,50 @@ +/*=================================================================== + +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. + +===================================================================*/ + +#ifndef mitkXmlSceneIO_h_included +#define mitkXmlSceneIO_h_included + +#include "mitkDataStorage.h" + +class TiXmlElement; + +namespace mitk +{ +class PropertyListsXmlFileReaderAndWriter; + +class PropertyListsXmlFileReaderAndWriter : public itk::Object +{ + public: + + mitkClassMacro( PropertyListsXmlFileReaderAndWriter, itk::Object ); + itkNewMacro(Self); + + bool WriteLists( const std::string& fileName, const std::map& _PropertyLists ) const; + bool ReadLists( const std::string& fileName, std::map& _PropertyLists ) const; + + protected: + + PropertyListsXmlFileReaderAndWriter(); + virtual ~PropertyListsXmlFileReaderAndWriter(); + + bool PropertyFromXmlElem(std::string& name, mitk::BaseProperty::Pointer& prop, TiXmlElement* elem) const; + bool PropertyToXmlElem(const std::string& name, const mitk::BaseProperty* prop, TiXmlElement* elem) const; +}; + +} + +#endif +