diff --git a/Core/Code/DataManagement/mitkPropertyList.cpp b/Core/Code/DataManagement/mitkPropertyList.cpp index 94278f7332..9c74057c8f 100644 --- a/Core/Code/DataManagement/mitkPropertyList.cpp +++ b/Core/Code/DataManagement/mitkPropertyList.cpp @@ -1,284 +1,351 @@ /*=================================================================== 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 "mitkPropertyList.h" #include "mitkProperties.h" #include "mitkStringProperty.h" #include "mitkVector.h" mitk::BaseProperty* mitk::PropertyList::GetProperty(const std::string& propertyKey) const { PropertyMap::const_iterator it; it=m_Properties.find( propertyKey ); if(it!=m_Properties.end()) return it->second; else return NULL; } void mitk::PropertyList::SetProperty(const std::string& propertyKey, BaseProperty* property) { if (!property) return; //make sure that BaseProperty*, which may have just been created and never been //assigned to a SmartPointer, is registered/unregistered properly. If we do not //do that, it will a) not deleted in case it is identical to the old one or //b) possibly deleted when temporarily added to a smartpointer somewhere below. BaseProperty::Pointer tmpSmartPointerToProperty = property; PropertyMap::iterator it( m_Properties.find( propertyKey ) ); // Is a property with key @a propertyKey contained in the list? if( it != m_Properties.end() ) { // yes //is the property contained in the list identical to the new one? if( it->second->operator==(*property) ) { // yes? do nothing and return. return; } if (it->second->AssignProperty(*property)) { // The assignment was successfull this->Modified(); } else { MITK_ERROR << "In " __FILE__ ", l." << __LINE__ << ": Trying to set existing property " << it->first << " of type " << it->second->GetNameOfClass() << " to a property with different type " << property->GetNameOfClass() << "." << " Use ReplaceProperty() instead." << std::endl; } return; } //no? add it. PropertyMapElementType newProp; newProp.first = propertyKey; newProp.second = property; m_Properties.insert ( newProp ); this->Modified(); } void mitk::PropertyList::ReplaceProperty(const std::string& propertyKey, BaseProperty* property) { if (!property) return; PropertyMap::iterator it( m_Properties.find( propertyKey ) ); // Is a property with key @a propertyKey contained in the list? if( it != m_Properties.end() ) { it->second=NULL; m_Properties.erase(it); } //no? add/replace it. PropertyMapElementType newProp; newProp.first = propertyKey; newProp.second = property; m_Properties.insert ( newProp ); Modified(); } mitk::PropertyList::PropertyList() { } mitk::PropertyList::PropertyList(const mitk::PropertyList& other) : itk::Object() { for (PropertyMap::const_iterator i = other.m_Properties.begin(); i != other.m_Properties.end(); ++i) { m_Properties.insert(std::make_pair(i->first, i->second->Clone())); } } mitk::PropertyList::~PropertyList() { Clear(); } /** * Consider the list as changed when any of the properties has changed recently. */ unsigned long mitk::PropertyList::GetMTime() const { for ( PropertyMap::const_iterator it = m_Properties.begin() ; it != m_Properties.end(); ++it ) { if( it->second.IsNull() ) { itkWarningMacro(<< "Property '" << it->first <<"' contains nothing (NULL)."); continue; } if( Superclass::GetMTime() < it->second->GetMTime() ) { Modified(); break; } } return Superclass::GetMTime(); } bool mitk::PropertyList::DeleteProperty(const std::string& propertyKey) { PropertyMap::iterator it; it=m_Properties.find( propertyKey ); if(it!=m_Properties.end()) { it->second=NULL; m_Properties.erase(it); Modified(); return true; } return false; } void mitk::PropertyList::Clear() { PropertyMap::iterator it = m_Properties.begin(), end = m_Properties.end(); while(it!=end) { it->second = NULL; ++it; } m_Properties.clear(); } itk::LightObject::Pointer mitk::PropertyList::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); return result; } void mitk::PropertyList::ConcatenatePropertyList(PropertyList *pList, bool replace) { if (pList) { const PropertyMap* propertyMap = pList->GetMap(); for ( PropertyMap::const_iterator iter = propertyMap->begin(); // m_PropertyList is created in the constructor, so we don't check it here iter != propertyMap->end(); ++iter ) { const std::string key = iter->first; BaseProperty* value = iter->second; if (replace) { ReplaceProperty( key.c_str(), value ); } else { SetProperty( key.c_str(), value ); } } } } bool mitk::PropertyList::GetBoolProperty(const char* propertyKey, bool& boolValue) const { BoolProperty *gp = dynamic_cast( GetProperty(propertyKey) ); if ( gp != NULL ) { boolValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs //return GetPropertyValue(propertyKey, boolValue); } bool mitk::PropertyList::GetIntProperty(const char* propertyKey, int &intValue) const { IntProperty *gp = dynamic_cast( GetProperty(propertyKey) ); if ( gp != NULL ) { intValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs //return GetPropertyValue(propertyKey, intValue); } bool mitk::PropertyList::GetFloatProperty(const char* propertyKey, float &floatValue) const { FloatProperty *gp = dynamic_cast( GetProperty(propertyKey) ); if ( gp != NULL ) { floatValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs //return GetPropertyValue(propertyKey, floatValue); } bool mitk::PropertyList::GetStringProperty(const char* propertyKey, std::string& stringValue) const { StringProperty* sp= dynamic_cast(GetProperty(propertyKey)); if ( sp != NULL ) { stringValue = sp->GetValue(); return true; } return false; } void mitk::PropertyList::SetIntProperty(const char* propertyKey, int intValue) { SetProperty(propertyKey, mitk::IntProperty::New(intValue)); } void mitk::PropertyList::SetBoolProperty( const char* propertyKey, bool boolValue) { SetProperty(propertyKey, mitk::BoolProperty::New(boolValue)); } void mitk::PropertyList::SetFloatProperty( const char* propertyKey, float floatValue) { SetProperty(propertyKey, mitk::FloatProperty::New(floatValue)); } void mitk::PropertyList::SetStringProperty( const char* propertyKey, const char* stringValue) { SetProperty(propertyKey, mitk::StringProperty::New(stringValue)); } + +void mitk::PropertyList::Set( const char* propertyKey, bool boolValue ) +{ + this->SetBoolProperty( propertyKey, boolValue ); +} + +void mitk::PropertyList::Set( const char* propertyKey, int intValue ) +{ + this->SetIntProperty(propertyKey, intValue); +} + +void mitk::PropertyList::Set( const char* propertyKey, float floatValue ) +{ + this->SetFloatProperty(propertyKey, floatValue); +} + +void mitk::PropertyList::Set( const char* propertyKey, double doubleValue ) +{ + this->SetDoubleProperty(propertyKey, doubleValue); +} + +void mitk::PropertyList::Set( const char* propertyKey, const char* stringValue ) +{ + this->SetStringProperty(propertyKey, stringValue); +} + +bool mitk::PropertyList::Get( const char* propertyKey, bool& boolValue ) const +{ + return this->GetBoolProperty( propertyKey, boolValue ); +} + +bool mitk::PropertyList::Get( const char* propertyKey, int &intValue ) const +{ + return this->GetIntProperty(propertyKey, intValue); +} + +bool mitk::PropertyList::Get( const char* propertyKey, float &floatValue ) const +{ + return this->GetFloatProperty( propertyKey, floatValue ); +} + +bool mitk::PropertyList::Get( const char* propertyKey, double &doubleValue ) const +{ + return this->GetDoubleProperty( propertyKey, doubleValue ); +} + +bool mitk::PropertyList::Get( const char* propertyKey, std::string& stringValue ) const +{ + return this->GetStringProperty( propertyKey, stringValue ); +} + +bool mitk::PropertyList::GetDoubleProperty( const char* propertyKey, double &doubleValue ) const +{ + DoubleProperty *gp = dynamic_cast( GetProperty(propertyKey) ); + if ( gp != NULL ) + { + doubleValue = gp->GetValue(); + return true; + } + return false; + +} + +void mitk::PropertyList::SetDoubleProperty( const char* propertyKey, double doubleValue ) +{ + SetProperty(propertyKey, mitk::DoubleProperty::New(doubleValue)); +} diff --git a/Core/Code/DataManagement/mitkPropertyList.h b/Core/Code/DataManagement/mitkPropertyList.h index 233fd52e79..eb5de870cc 100644 --- a/Core/Code/DataManagement/mitkPropertyList.h +++ b/Core/Code/DataManagement/mitkPropertyList.h @@ -1,210 +1,260 @@ /*=================================================================== 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 PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #define PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #include #include "mitkBaseProperty.h" #include "mitkGenericProperty.h" #include "mitkUIDGenerator.h" #include #include #include namespace mitk { class XMLWriter; /** * @brief Key-value list holding instances of BaseProperty * * This list is meant to hold an arbitrary list of "properties", * which should describe the object associated with this list. * * Usually you will use PropertyList as part of a DataNode * object - in this context the properties describe the data object * held by the DataNode (e.g. whether the object is rendered at * all, which color is used for rendering, what name should be * displayed for the object, etc.) * * The values in the list are not fixed, you may introduce any kind * of property that seems useful - all you have to do is inherit * from BaseProperty. * * The list is organized as a key-value pairs, i.e. * * \li "name" : pointer to a StringProperty * \li "visible" : pointer to a BoolProperty * \li "color" : pointer to a ColorProperty * \li "volume" : pointer to a FloatProperty * * Please see the documentation of SetProperty and ReplaceProperty for two * quite different semantics. Normally SetProperty is what you want - this * method will try to change the value of an existing property and will * not allow you to replace e.g. a ColorProperty with an IntProperty. * * @ingroup DataManagement */ class MITK_CORE_EXPORT PropertyList : public itk::Object { public: mitkClassMacro(PropertyList, itk::Object) /** * Method for creation through the object factory. */ itkNewMacro(Self) /** * Map structure to hold the properties: the map key is a string, * the value consists of the actual property object (BaseProperty). */ typedef std::map< std::string, BaseProperty::Pointer> PropertyMap; typedef std::pair< std::string, BaseProperty::Pointer> PropertyMapElementType; /** * @brief Get a property by its name. */ mitk::BaseProperty* GetProperty(const std::string& propertyKey) const; /** * @brief Set a property in the list/map by value. * * The actual OBJECT holding the value of the property is not replaced, but its value * is modified to match that of @a property. To really replace the object holding the * property - which would make sense if you want to change the type (bool, string) of the property * - call ReplaceProperty. */ void SetProperty(const std::string& propertyKey, BaseProperty* property); /** * @brief Set a property object in the list/map by reference. * * The actual OBJECT holding the value of the property is replaced by this function. * This is useful if you want to change the type of the property, like from BoolProperty to StringProperty. * Another use is to share one and the same property object among several ProperyList/DataNode objects, which * makes them appear synchronized. */ void ReplaceProperty(const std::string& propertyKey, BaseProperty* property); /** * @brief Set a property object in the list/map by reference. */ void ConcatenatePropertyList(PropertyList *pList, bool replace = false); //##Documentation //## @brief Convenience access method for GenericProperty properties //## (T being the type of the second parameter) //## @return @a true property was found template bool GetPropertyValue(const char* propertyKey, T & value) const { GenericProperty* gp= dynamic_cast*>(GetProperty(propertyKey)); if ( gp != NULL ) { value = gp->GetValue(); return true; } return false; } /** * @brief Convenience method to access the value of a BoolProperty */ bool GetBoolProperty(const char* propertyKey, bool& boolValue) const; + /** + * @brief ShortCut for the above method + */ + bool Get(const char* propertyKey, bool& boolValue) const; /** * @brief Convenience method to set the value of a BoolProperty */ void SetBoolProperty( const char* propertyKey, bool boolValue); + /** + * @brief ShortCut for the above method + */ + void Set( const char* propertyKey, bool boolValue); /** * @brief Convenience method to access the value of an IntProperty */ bool GetIntProperty(const char* propertyKey, int &intValue) const; + /** + * @brief ShortCut for the above method + */ + bool Get(const char* propertyKey, int &intValue) const; /** * @brief Convenience method to set the value of an IntProperty */ void SetIntProperty(const char* propertyKey, int intValue); + /** + * @brief ShortCut for the above method + */ + void Set(const char* propertyKey, int intValue); /** * @brief Convenience method to access the value of a FloatProperty */ bool GetFloatProperty(const char* propertyKey, float &floatValue) const; + /** + * @brief ShortCut for the above method + */ + bool Get(const char* propertyKey, float &floatValue) const; /** * @brief Convenience method to set the value of a FloatProperty */ void SetFloatProperty( const char* propertyKey, float floatValue); + /** + * @brief ShortCut for the above method + */ + void Set( const char* propertyKey, float floatValue); + + /** + * @brief Convenience method to access the value of a DoubleProperty + */ + bool GetDoubleProperty(const char* propertyKey, double &doubleValue) const; + /** + * @brief ShortCut for the above method + */ + bool Get(const char* propertyKey, double &doubleValue) const; + + /** + * @brief Convenience method to set the value of a DoubleProperty + */ + void SetDoubleProperty( const char* propertyKey, double doubleValue); + /** + * @brief ShortCut for the above method + */ + void Set( const char* propertyKey, double doubleValue); /** * @brief Convenience method to access the value of a StringProperty */ bool GetStringProperty(const char* propertyKey, std::string& stringValue) const; + /** + * @brief ShortCut for the above method + */ + bool Get(const char* propertyKey, std::string& stringValue) const; /** * @brief Convenience method to set the value of a StringProperty */ void SetStringProperty( const char* propertyKey, const char* stringValue); + /** + * @brief ShortCut for the above method + */ + void Set( const char* propertyKey, const char* stringValue); /** * @brief Get the timestamp of the last change of the map or the last change of one of * the properties store in the list (whichever is later). */ virtual unsigned long GetMTime() const; /** * @brief Remove a property from the list/map. */ bool DeleteProperty(const std::string& propertyKey); const PropertyMap* GetMap() const { return &m_Properties; } bool IsEmpty() const { return m_Properties.empty(); } virtual void Clear(); protected: PropertyList(); PropertyList(const PropertyList& other); virtual ~PropertyList(); /** * @brief Map of properties. */ PropertyMap m_Properties; private: virtual itk::LightObject::Pointer InternalClone() const; }; } // namespace mitk #endif /* PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D */ diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index 2359420bd4..c03fbefa94 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -1,65 +1,66 @@ set(LIBPOSTFIX "Ext") # Modules must be listed according to their dependencies set(module_dirs SceneSerializationBase PlanarFigure ImageExtraction ImageStatistics LegacyAdaptors IpPicSupport MitkExt SceneSerialization GraphAlgorithms ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation Qmitk QmitkExt SegmentationUI DiffusionImaging GPGPU IGTBase IGT CameraCalibration IGTUI RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport Overlays InputDevices ToFHardware ToFProcessing ToFUI US ClippingTools USUI DicomUI Simulation Remeshing Python + Persistence ) set(MITK_DEFAULT_SUBPROJECTS MITK-Modules) foreach(module_dir ${module_dirs}) add_subdirectory(${module_dir}) endforeach() if(MITK_PRIVATE_MODULES) file(GLOB all_subdirs RELATIVE ${MITK_PRIVATE_MODULES} ${MITK_PRIVATE_MODULES}/*) foreach(subdir ${all_subdirs}) string(FIND ${subdir} "." _result) if(_result EQUAL -1) if(EXISTS ${MITK_PRIVATE_MODULES}/${subdir}/CMakeLists.txt) message(STATUS "Found private module ${subdir}") add_subdirectory(${MITK_PRIVATE_MODULES}/${subdir} private_modules/${subdir}) endif() endif() endforeach() endif(MITK_PRIVATE_MODULES) diff --git a/Modules/Persistence/CMakeLists.txt b/Modules/Persistence/CMakeLists.txt index 8f2e5e9d7a..b132706de7 100644 --- a/Modules/Persistence/CMakeLists.txt +++ b/Modules/Persistence/CMakeLists.txt @@ -1,5 +1,5 @@ MITK_CREATE_MODULE( Persistence INCLUDE_DIRS - DEPENDS Mitk + DEPENDS SceneSerialization ) -add_subdirectory(Testing) +add_subdirectory(Testing) \ No newline at end of file diff --git a/Modules/Persistence/TODO.txt b/Modules/Persistence/TODO.txt new file mode 100644 index 0000000000..9b03f9f9d0 --- /dev/null +++ b/Modules/Persistence/TODO.txt @@ -0,0 +1,8 @@ +1. sceneIO holt sich propertylists vom persistenceservice (NICHT umgekehrt) +2. "erweiterte" propertylist, um komfortabel zugreifen zu können (klammer operator)-> sceneIO aufbohren +3. ähnelt sehr dem configuration service (vll den nehmen) + +PLAN +1. configuration service anschauen +2. einfache implementierung des interfaces wie es ist +3. sceneIO aufbohren (evtl erweiterte proplist) \ No newline at end of file diff --git a/Modules/Persistence/Testing/files.cmake b/Modules/Persistence/Testing/files.cmake index dbb46bd12b..cbf6894db4 100644 --- a/Modules/Persistence/Testing/files.cmake +++ b/Modules/Persistence/Testing/files.cmake @@ -1,2 +1,3 @@ set(MODULE_TESTS +mitkPersistenceTest.cpp ) diff --git a/Modules/Persistence/Testing/mitkPersistenceTest.cpp b/Modules/Persistence/Testing/mitkPersistenceTest.cpp new file mode 100644 index 0000000000..2ffdbff379 --- /dev/null +++ b/Modules/Persistence/Testing/mitkPersistenceTest.cpp @@ -0,0 +1,65 @@ +/*=================================================================== + +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 + +// redefine get module context macro +#define PERSISTENCE_GET_MODULE_CONTEXT\ + us::ModuleContext* context = mitk::PersistenceService::GetModuleContext(); + + +struct PersistenceTestClass +{ + PersistenceTestClass() + : id(""), param1(1), param2(2), param3(false) + { + } + std::string id; + int param1; + double param2; + bool param3; + + PERSISTENCE_CREATE_SAVE3(id, param1, param2, param3) + PERSISTENCE_CREATE_LOAD3(id, param1, param2, param3) +}; + + +int mitkPersistenceTest(int /*argc*/, char* /*argv*/[]) +{ + MITK_TEST_BEGIN("PersistenceTest") + + PersistenceTestClass testClass; + testClass.id = "testClass"; + testClass.param1 = 100; + testClass.param2 = 200.56; + testClass.param3 = true; + MITK_TEST_CONDITION_REQUIRED( testClass.Save(), "testClass.Save()"); + + PersistenceTestClass testClass2; + testClass.id = "testClass"; + MITK_TEST_CONDITION_REQUIRED( testClass2.Load(), "testClass.Save()"); + + + 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" ); + + MITK_TEST_END() +} diff --git a/Modules/Persistence/files.cmake b/Modules/Persistence/files.cmake index 0b7b177e34..adb46e5f7b 100644 --- a/Modules/Persistence/files.cmake +++ b/Modules/Persistence/files.cmake @@ -1,2 +1,6 @@ set(CPP_FILES +mitkIPersistenceService.cpp +mitkPersistenceService.cpp +mitkPropertyListReplacedObserver.cpp +mitkPersistenceActivator.cpp ) diff --git a/Modules/Persistence/mitkIPersistenceService.h b/Modules/Persistence/mitkIPersistenceService.h index d63d8c9721..4b12426478 100644 --- a/Modules/Persistence/mitkIPersistenceService.h +++ b/Modules/Persistence/mitkIPersistenceService.h @@ -1,100 +1,190 @@ /*=================================================================== 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 "MitkExtExports.h" -#include "mitkImage.h" +#include "mitkPropertyListReplacedObserver.h" +#include "usServiceReference.h" +#include "usModuleContext.h" //for microservices #include -#include "mitkSurface.h" -#include namespace mitk { - /// - /// a PropertyListReplacedObserver gets informed as soon as a PropertyList with a given id was replaced during a Load() process - /// \see IPersistenceService::AddPropertyListReplacedObserver() - /// - class PropertyListReplacedObserver - { - public: - /// - /// will be called *before* the propertyList gets replaced with new contents, i.e. propertyList still contains the old values - /// - virtual void BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) {}; - /// - /// will be called *after* the propertyList gets replaced with new contents, i.e. propertyList contains the new values - /// - virtual void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) {}; - }; - /// /// The central service for the persistence module - /// Basic idea is to create PropertyLists with a unique id using GetPropertyList(). A consumer + /// 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 MitkExt_EXPORT IPersistenceService + class Persistence_EXPORT IPersistenceService { public: /// /// If PropertyList with the given id exists, returns it. Otherwise creates a new one and returns it. - /// \return false if id already exists, true otherwise + /// 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 bool AddPropertyList( const std::string& id, mitk::PropertyList* propertyList ) = 0; + virtual mitk::PropertyList::Pointer GetPropertyList( std::string& id, bool* existed=0 ) = 0; /// /// Save the current PropertyLists to fileName. If fileName is empty, a special file in the users home directory will be used. /// \return false if an error occured (cannot write to file), true otherwise /// virtual bool Save(const std::string& fileName="") = 0; /// /// Load PropertyLists from fileName. If fileName is empty, a special file in the users home directory will be used. /// *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="") = 0; /// /// Using SetAutoLoadAndSave(true) will cause the service to load/save the property lists at application /// start/stop. /// - virtual void SetAutoLoadAndSave(bool autoLoadAndSave); + virtual void SetAutoLoadAndSave(bool autoLoadAndSave) = 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\ + us::ModuleContext* context = GetModuleContext(); + +#define PERSISTENCE_GET_SERVICE\ + PERSISTENCE_GET_MODULE_CONTEXT\ + us::ServiceReference persistenceServiceRef = context->GetServiceReference();\ + mitk::IPersistenceService* persistenceService = dynamic_cast ( context->GetService(persistenceServiceRef) ); + +#define PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ +bool Save() { \ + PERSISTENCE_GET_SERVICE\ + bool noError = persistenceService != 0;\ + mitk::PropertyList::Pointer propList;\ + if( noError ) {\ + propList = persistenceService->GetPropertyList(IdMemberName); + +#define PERSISTENCE_CREATE_SAVE_END\ + }\ + noError = persistenceService->Save();\ + return noError;\ +} + +#define PERSISTENCE_CREATE_SAVE(IdMemberName, ParamMemberName)\ + PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ + propList->Set( "ParamMemberName", ParamMemberName );\ + PERSISTENCE_CREATE_SAVE_END + +#define PERSISTENCE_CREATE_SAVE2(IdMemberName, ParamMemberName, ParamMember2Name)\ + PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ + propList->Set( "ParamMemberName", ParamMemberName );\ + propList->Set( "ParamMember2Name", ParamMember2Name );\ + PERSISTENCE_CREATE_SAVE_END + +#define PERSISTENCE_CREATE_SAVE3(IdMemberName, ParamMemberName, ParamMember2Name, ParamMember3Name)\ + PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ + propList->Set( "ParamMemberName", ParamMemberName );\ + propList->Set( "ParamMember2Name", ParamMember2Name );\ + propList->Set( "ParamMember3Name", ParamMember3Name );\ + PERSISTENCE_CREATE_SAVE_END + +#define PERSISTENCE_CREATE_SAVE4(IdMemberName, ParamMemberName, ParamMember2Name, ParamMember3Name, ParamMember4Name)\ + PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ + propList->Set( "ParamMemberName", ParamMemberName );\ + propList->Set( "ParamMember2Name", ParamMember2Name );\ + propList->Set( "ParamMember3Name", ParamMember3Name );\ + propList->Set( "ParamMember4Name", ParamMember4Name );\ + PERSISTENCE_CREATE_SAVE_END + +#define PERSISTENCE_CREATE_SAVE5(IdMemberName, ParamMemberName, ParamMember2Name, ParamMember3Name, Param4Name, ParamMember5Name)\ + PERSISTENCE_CREATE_SAVE_START(IdMemberName)\ + propList->Set( "ParamMemberName", ParamMemberName );\ + propList->Set( "ParamMember2Name", ParamMember2Name );\ + propList->Set( "ParamMember3Name", ParamMember3Name );\ + propList->Set( "ParamMember4Name", ParamMember4Name );\ + propList->Set( "ParamMember5Name", ParamMember5Name );\ + PERSISTENCE_CREATE_SAVE_END + +/// MACROS FOR AUTOMATIC LOAD FUNCTION +#define PERSISTENCE_CREATE_LOAD_START(IdMemberName)\ +bool Load() {\ + PERSISTENCE_GET_SERVICE\ + bool noError = persistenceService != 0 && persistenceService->Load();\ + if( noError ) { + +#define PERSISTENCE_CREATE_LOAD_END\ + }\ + return noError;\ +} + +#define PERSISTENCE_CREATE_LOAD(IdMemberName, ParamMemberName)\ + PERSISTENCE_CREATE_LOAD_START(IdMemberName)\ + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(IdMemberName);\ + noError = propList->Get( "ParamMemberName", ParamMemberName );\ + PERSISTENCE_CREATE_LOAD_END + +#define PERSISTENCE_CREATE_LOAD2(IdMemberName, ParamMemberName, Param2MemberName)\ + PERSISTENCE_CREATE_LOAD_START(IdMemberName)\ + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(IdMemberName);\ + noError = propList->Get( "ParamMemberName", ParamMemberName );\ + if(noError)\ + noError = propList->Get( "Param2MemberName", Param2MemberName );\ + PERSISTENCE_CREATE_LOAD_END + +#define PERSISTENCE_CREATE_LOAD3(IdMemberName, ParamMemberName, Param2MemberName, Param3MemberName)\ + PERSISTENCE_CREATE_LOAD_START(IdMemberName)\ + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(IdMemberName);\ + noError = propList->Get( "ParamMemberName", ParamMemberName );\ + if(noError)\ + noError = propList->Get( "Param2MemberName", Param2MemberName );\ + if(noError)\ + noError = propList->Get( "Param3MemberName", Param3MemberName );\ + PERSISTENCE_CREATE_LOAD_END + +#define PERSISTENCE_CREATE_LOAD4(IdMemberName, ParamMemberName, Param2MemberName, Param3MemberName, Param4MemberName)\ + PERSISTENCE_CREATE_LOAD_START(IdMemberName)\ + mitk::PropertyList::Pointer propList = persistenceService->GetPropertyList(IdMemberName);\ + noError = propList->Get( "ParamMemberName", ParamMemberName );\ + if(noError)\ + noError = propList->Get( "Param2MemberName", Param2MemberName );\ + if(noError)\ + noError = propList->Get( "Param3MemberName", Param3MemberName );\ + if(noError)\ + noError = propList->Get( "Param4MemberName", Param4MemberName );\ + PERSISTENCE_CREATE_LOAD_END + US_DECLARE_SERVICE_INTERFACE(mitk::IPersistenceService, "org.mitk.services.IPersistenceService") #endif diff --git a/Modules/Persistence/mitkPersistenceActivator.cpp b/Modules/Persistence/mitkPersistenceActivator.cpp new file mode 100644 index 0000000000..c828a84b78 --- /dev/null +++ b/Modules/Persistence/mitkPersistenceActivator.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +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 mitkPersistenceActivator_h +#define mitkPersistenceActivator_h + +// Microservices +#include +#include "mitkPersistenceService.h" +#include + +namespace mitk +{ + /// + /// installs the PersistenceService + /// runs all initial commands (setting env paths etc) + /// + class PersistenceActivator : public us::ModuleActivator + { + public: + + void Load(us::ModuleContext* context) + { + MITK_DEBUG << "PersistenceActivator::Load"; + // Registering PersistenceService as MicroService + m_PersistenceService = itk::SmartPointer(new PersistenceService()); + + us::ServiceProperties _PersistenceServiceProps; + _PersistenceServiceProps["Name"] = std::string("PersistenceService"); + + m_PersistenceServiceRegistration = context->RegisterService(m_PersistenceService, _PersistenceServiceProps); + } + + void Unload(us::ModuleContext* context) + { + MITK_DEBUG("PersistenceActivator") << "PersistenceActivator::Unload"; + MITK_DEBUG("PersistenceActivator") << "m_PersistenceService GetReferenceCount " << m_PersistenceService->GetReferenceCount(); + m_PersistenceServiceRegistration.Unregister(); + m_PersistenceService->Delete(); + MITK_DEBUG("PersistenceActivator") << "m_PersistenceService GetReferenceCount " << m_PersistenceService->GetReferenceCount(); + } + + virtual ~PersistenceActivator() + { + } + + private: + itk::SmartPointer m_PersistenceService; + us::ServiceRegistration m_PersistenceServiceRegistration; + }; +} + +US_EXPORT_MODULE_ACTIVATOR(Persistence, mitk::PersistenceActivator) +#endif diff --git a/Modules/Persistence/mitkPersistenceService.cpp b/Modules/Persistence/mitkPersistenceService.cpp new file mode 100644 index 0000000000..68e964b925 --- /dev/null +++ b/Modules/Persistence/mitkPersistenceService.cpp @@ -0,0 +1,216 @@ +/*=================================================================== + +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 + +std::string mitk::PersistenceService::CreateDefaultFileName() +{ + std::string homeDir = Poco::Path::home(); + std::string file = homeDir + "PersistenceService.mitk"; + return file; +} + +const std::string mitk::PersistenceService::DEFAULT_FILE_NAME(CreateDefaultFileName()); + +const std::string mitk::PersistenceService::PERSISTENCE_PROPERTY_NAME("PersistenceNode"); + +const std::string mitk::PersistenceService::PERSISTENCE_PROPERTYLIST_NAME("PersistenceService"); + + +mitk::PersistenceService::PersistenceService() + : m_AutoLoadAndSave( false ), m_SceneIO( SceneIO::New() ) +{ + { + MITK_DEBUG("mitk::PersistenceService") << "constructing PersistenceService"; + } + + MITK_DEBUG("mitk::PersistenceService") << "loading PersistenceService personal persitent data"; + this->Load( DEFAULT_FILE_NAME ); + std::string id = PERSISTENCE_PROPERTYLIST_NAME; + mitk::PropertyList::Pointer propList = this->GetPropertyList( id ); + propList->GetBoolProperty("m_AutoLoadAndSave", m_AutoLoadAndSave); + + if( m_AutoLoadAndSave == false ) + { + MITK_DEBUG("mitk::PersistenceService") << "autoloading was not wished. clearing data we got so far."; + m_PropertyLists.clear(); + } +} + +mitk::PersistenceService::~PersistenceService() +{ + MITK_DEBUG("mitk::PersistenceService") << "destructing PersistenceService"; +} + +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 ) +{ + 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() ) + { + to->SetProperty( (*propMapIt).first, (*propMapIt).second->Clone() ); + ++propMapIt; + } +} + +bool mitk::PersistenceService::Save(const std::string& fileName) +{ + bool save = false; + mitk::StandaloneDataStorage::Pointer tempDs = mitk::StandaloneDataStorage::New(); + + std::map::iterator it = m_PropertyLists.begin(); + while( it != m_PropertyLists.end() ) + { + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + + this->ClonePropertyList( (*it).second, newNode->GetPropertyList() ); + + newNode->SetBoolProperty( PERSISTENCE_PROPERTY_NAME.c_str(), true ); + newNode->SetName( (*it).first ); + + tempDs->Add(newNode); + ++it; + } + + mitk::NodePredicateProperty::Pointer pred = + mitk::NodePredicateProperty::New(PERSISTENCE_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + + mitk::DataStorage::SetOfObjects::ConstPointer rs = tempDs->GetSubset(pred); + + return m_SceneIO->SaveScene( rs, tempDs, fileName ); +} + +bool mitk::PersistenceService::Load(const std::string& fileName) +{ + bool load = false; + + DataStorage::Pointer ds = m_SceneIO->LoadScene( fileName ); + load = m_SceneIO->GetFailedNodes() == 0 && m_SceneIO->GetFailedProperties() == 0; + if( !load ) + { + MITK_DEBUG("mitk::PersistenceService") << "loading of scene files failed"; + return load; + } + + DataStorage::SetOfObjects::ConstPointer allNodes = ds->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 ) + { + 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", 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 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(); +} diff --git a/Modules/Persistence/mitkPersistenceService.h b/Modules/Persistence/mitkPersistenceService.h new file mode 100644 index 0000000000..75ae6abe88 --- /dev/null +++ b/Modules/Persistence/mitkPersistenceService.h @@ -0,0 +1,60 @@ +/*=================================================================== + +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 +#include "mitkSceneIO.h" + +namespace mitk +{ + /// + /// implementation of the IPersistenceService + /// \see IPersistenceService + class Persistence_EXPORT PersistenceService: public itk::LightObject, public mitk::IPersistenceService + { + public: + static std::string CreateDefaultFileName(); + static const std::string DEFAULT_FILE_NAME; + static const std::string PERSISTENCE_PROPERTY_NAME; + static const std::string PERSISTENCE_PROPERTYLIST_NAME; + static us::ModuleContext* GetModuleContext(); + + PersistenceService(); + + ~PersistenceService(); + + mitk::PropertyList::Pointer GetPropertyList( std::string& id, bool* existed=0 ); + + bool Save(const std::string& fileName=""); + + bool Load(const std::string& fileName=""); + + void SetAutoLoadAndSave(bool autoLoadAndSave); + + void AddPropertyListReplacedObserver( PropertyListReplacedObserver* observer ); + + void RemovePropertyListReplacedObserver( PropertyListReplacedObserver* observer ); + private: + void ClonePropertyList( mitk::PropertyList* from, mitk::PropertyList* to ); + std::map m_PropertyLists; + bool m_AutoLoadAndSave; + std::set m_PropertyListReplacedObserver; + SceneIO::Pointer m_SceneIO; + }; +} +#endif diff --git a/Modules/Persistence/mitkPropertyListReplacedObserver.cpp b/Modules/Persistence/mitkPropertyListReplacedObserver.cpp new file mode 100644 index 0000000000..78c0302100 --- /dev/null +++ b/Modules/Persistence/mitkPropertyListReplacedObserver.cpp @@ -0,0 +1,25 @@ +/*=================================================================== + +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 "mitkPropertyListReplacedObserver.h" + +void mitk::PropertyListReplacedObserver::BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) +{ +} + +void mitk::PropertyListReplacedObserver::AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ) +{ +} diff --git a/Modules/Persistence/mitkPropertyListReplacedObserver.h b/Modules/Persistence/mitkPropertyListReplacedObserver.h new file mode 100644 index 0000000000..489dddaf85 --- /dev/null +++ b/Modules/Persistence/mitkPropertyListReplacedObserver.h @@ -0,0 +1,44 @@ +/*=================================================================== + +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 mitkPropertyListReplacedObserver_h +#define mitkPropertyListReplacedObserver_h + +// mitk +#include "PersistenceExports.h" +#include "mitkPropertyList.h" +#include + +namespace mitk +{ + /// + /// a PropertyListReplacedObserver gets informed as soon as a PropertyList with a given id was replaced during a Load() process + /// \see IPersistenceService::AddPropertyListReplacedObserver() + /// + class Persistence_EXPORT PropertyListReplacedObserver + { + public: + /// + /// will be called *before* the propertyList gets replaced with new contents, i.e. propertyList still contains the old values + /// + virtual void BeforePropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ); + /// + /// will be called *after* the propertyList gets replaced with new contents, i.e. propertyList contains the new values + /// + virtual void AfterPropertyListReplaced( const std::string& id, mitk::PropertyList* propertyList ); + }; +} // namespace mitk + +#endif // mitkPropertyListReplacedObserver_h