diff --git a/Modules/Core/include/mitkCoreObjectFactory.h b/Modules/Core/include/mitkCoreObjectFactory.h index c1a28c340c..d634079cc6 100644 --- a/Modules/Core/include/mitkCoreObjectFactory.h +++ b/Modules/Core/include/mitkCoreObjectFactory.h @@ -1,145 +1,181 @@ /*=================================================================== 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 COREOBJECTFACTORY_H_INCLUDED #define COREOBJECTFACTORY_H_INCLUDED #include #include "mitkCoreObjectFactoryBase.h" #include "mitkFileWriterWithInformation.h" #include #include #include namespace mitk { class Event; class LegacyFileReaderService; class LegacyFileWriterService; class LegacyImageWriterService; class MITKCORE_EXPORT CoreObjectFactory : public CoreObjectFactoryBase { public: - mitkClassMacro(CoreObjectFactory, CoreObjectFactoryBase) itkFactorylessNewMacro(CoreObjectFactory) + mitkClassMacro(CoreObjectFactory, CoreObjectFactoryBase) itkFactorylessNewMacro(CoreObjectFactory); - Mapper::Pointer CreateMapper(mitk::DataNode *node, MapperSlotId slotId) override; + /** + * @brief This function returns a mapper for use + * + * It first searches the service registry for fitting service references and if found fetches a mapper service by + * calling @see GetMapperFromServiceRegistry(ref, node) + * + * If no service is found this function falls back to the old + * way of checking extra factories and instantiating mappers directly + * @param node The data node that requires a mapper + * @param id The SlotId the mapper has to support + * @return The found / created mapper or nullptr if no mapper fits the parameters + */ + Mapper::Pointer CreateMapper(mitk::DataNode *node, MapperSlotId id) override; + /** + * @brief Gets a mapper service + * @param ref The us::ServiceReference specifying which mapper shall be fetched + * @param consumer As of now the consuming DataNode is tracked in order to notify it if the mapper service in use is + * unregistering, which will invalidate the mapper instance. + * This could be replaced by a check-before-use on the DataNode's side + * @return A mapper (service) or nullptr if ref is invalid + * + * \note Mapper services aqcuired through this class should be released if no longer needed by calling + * UngetMapperFromServiceRegistry(mapper) + */ + Mapper::Pointer GetMapperFromServiceRegistry(us::ServiceReference ref, DataNode *consumer); + /** + * @brief Removes this mapper service (instance) from the registry which will release it's memory + * @param mapperService The service (instance) to unget + */ + void UngetMapperFromServiceRegistry(Mapper *mapperService); void SetDefaultProperties(mitk::DataNode *node) override; virtual void MapEvent(const mitk::Event *event, const int eventID); virtual void RegisterExtraFactory(CoreObjectFactoryBase *factory); virtual void UnRegisterExtraFactory(CoreObjectFactoryBase *factory); static Pointer GetInstance(); ~CoreObjectFactory() override; /** * @brief This method gets the supported (open) file extensions as string. * * This string can then used by the Qt QFileDialog widget. * * @return The c-string that contains the file extensions * @deprecatedSince{2014_10} See mitk::FileReaderRegistry and QmitkIOUtil */ DEPRECATED(virtual const char *GetFileExtensions() override); /** * @brief get the defined (open) file extension map * * @return the defined (open) file extension map * @deprecatedSince{2014_10} See mitk::FileReaderRegistry and QmitkIOUtil */ DEPRECATED(virtual MultimapType GetFileExtensionsMap() override); /** * @brief This method gets the supported (save) file extensions as string. * * This string can then used by the Qt QFileDialog widget. * * @return The c-string that contains the (save) file extensions * @deprecatedSince{2014_10} See mitk::FileWriterRegistry and QmitkIOUtil */ DEPRECATED(virtual const char *GetSaveFileExtensions() override); /** * @brief get the defined (save) file extension map * * @return the defined (save) file extension map * @deprecatedSince{2014_10} See mitk::FileWriterRegistry and QmitkIOUtil */ MultimapType GetSaveFileExtensionsMap() override; /** * @deprecatedSince{2014_10} See mitk::FileWriterRegistry */ DEPRECATED(virtual FileWriterList GetFileWriters()); /** * @deprecatedSince{2014_10} See mitk::FileWriterRegistry and QmitkIOUtil */ DEPRECATED(std::string GetDescriptionForExtension(const std::string &extension)); protected: CoreObjectFactory(); /** * @brief Merge the input map into the fileExtensionsMap. Duplicate entries are removed * * @param fileExtensionsMap the existing map, it contains value pairs like * ("*.dcm", "DICOM files"),("*.dc3", "DICOM files"). * This map is extented/merged with the values from the input map. * @param inputMap the input map, it contains value pairs like ("*.dcm", * "DICOM files"),("*.dc3", "DICOM files") returned by the extra factories. * @deprecatedSince{2014_10} */ void MergeFileExtensions(MultimapType &fileExtensionsMap, MultimapType inputMap); /** * @brief initialize the file extension entries for open and save * @deprecatedSince{2014_10} */ void CreateFileExtensionsMap(); /** * @deprecatedSince{2014_10} */ DEPRECATED(void CreateSaveFileExtensions()); typedef std::set ExtraFactoriesContainer; ExtraFactoriesContainer m_ExtraFactories; FileWriterList m_FileWriters; std::string m_FileExtensions; MultimapType m_FileExtensionsMap; std::string m_SaveFileExtensions; MultimapType m_SaveFileExtensionsMap; private: + std::map, us::ServiceObjects> m_MapperServiceObjects; + std::map> m_MapperServices; + std::map, std::set> m_MapperConsumers; + + private: + Mapper::Pointer GetMapperFromServiceRegistry(DataNode *node, MapperSlotId id); + void RegisterLegacyReaders(mitk::CoreObjectFactoryBase *factory); void RegisterLegacyWriters(mitk::CoreObjectFactoryBase *factory); void UnRegisterLegacyReaders(mitk::CoreObjectFactoryBase *factory); void UnRegisterLegacyWriters(mitk::CoreObjectFactoryBase *factory); std::map> m_LegacyReaders; std::map> m_LegacyWriters; }; } // namespace mitk #endif diff --git a/Modules/Core/src/mitkCoreObjectFactory.cpp b/Modules/Core/src/mitkCoreObjectFactory.cpp index c8aaac22fb..53c644ed0e 100644 --- a/Modules/Core/src/mitkCoreObjectFactory.cpp +++ b/Modules/Core/src/mitkCoreObjectFactory.cpp @@ -1,487 +1,566 @@ /*=================================================================== 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 "mitkConfig.h" #include "mitkCoreObjectFactory.h" +#include "mitkConfig.h" #include "mitkColorProperty.h" #include "mitkDataNode.h" #include "mitkEnumerationProperty.h" #include "mitkGeometry3D.h" #include "mitkGeometryData.h" #include "mitkImage.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkPlaneGeometry.h" #include "mitkPlaneGeometryData.h" #include "mitkPlaneGeometryDataMapper2D.h" #include "mitkPlaneGeometryDataVtkMapper3D.h" #include "mitkPointSet.h" #include "mitkPointSetVtkMapper2D.h" #include "mitkPointSetVtkMapper3D.h" #include "mitkProperties.h" #include "mitkPropertyList.h" #include "mitkSlicedGeometry3D.h" #include "mitkSmartPointerProperty.h" #include "mitkStringProperty.h" #include "mitkSurface.h" #include "mitkSurfaceVtkMapper2D.h" #include "mitkSurfaceVtkMapper3D.h" #include "mitkTimeGeometry.h" #include "mitkTransferFunctionProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include // Legacy Support: #include "usLDAPProp.h" #include #include #include #include void mitk::CoreObjectFactory::RegisterExtraFactory(CoreObjectFactoryBase *factory) { MITK_DEBUG << "CoreObjectFactory: registering extra factory of type " << factory->GetNameOfClass(); m_ExtraFactories.insert(CoreObjectFactoryBase::Pointer(factory)); // Register Legacy Reader and Writer this->RegisterLegacyReaders(factory); this->RegisterLegacyWriters(factory); } void mitk::CoreObjectFactory::UnRegisterExtraFactory(CoreObjectFactoryBase *factory) { MITK_DEBUG << "CoreObjectFactory: un-registering extra factory of type " << factory->GetNameOfClass(); this->UnRegisterLegacyWriters(factory); this->UnRegisterLegacyReaders(factory); try { m_ExtraFactories.erase(factory); } catch (std::exception const &e) { MITK_ERROR << "Caugt exception while unregistering: " << e.what(); } } mitk::CoreObjectFactory::Pointer mitk::CoreObjectFactory::GetInstance() { static mitk::CoreObjectFactory::Pointer instance; if (instance.IsNull()) { instance = mitk::CoreObjectFactory::New(); } return instance; } mitk::CoreObjectFactory::~CoreObjectFactory() { for (auto iter = m_LegacyReaders.begin(); iter != m_LegacyReaders.end(); ++iter) { for (auto &elem : iter->second) { delete elem; } } for (auto iter = m_LegacyWriters.begin(); iter != m_LegacyWriters.end(); ++iter) { for (auto &elem : iter->second) { delete elem; } } } void mitk::CoreObjectFactory::SetDefaultProperties(mitk::DataNode *node) { if (node == nullptr) return; mitk::DataNode::Pointer nodePointer = node; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { mitk::ImageVtkMapper2D::SetDefaultProperties(node); } mitk::PlaneGeometryData::Pointer planeGeometry = dynamic_cast(node->GetData()); if (planeGeometry.IsNotNull()) { mitk::PlaneGeometryDataMapper2D::SetDefaultProperties(node); } mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if (surface.IsNotNull()) { mitk::SurfaceVtkMapper2D::SetDefaultProperties(node); mitk::SurfaceVtkMapper3D::SetDefaultProperties(node); } mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData()); if (pointSet.IsNotNull()) { mitk::PointSetVtkMapper2D::SetDefaultProperties(node); mitk::PointSetVtkMapper3D::SetDefaultProperties(node); } for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) { (*it)->SetDefaultProperties(node); } } mitk::CoreObjectFactory::CoreObjectFactory() { static bool alreadyDone = false; if (!alreadyDone) { CreateFileExtensionsMap(); // RegisterLegacyReaders(this); // RegisterLegacyWriters(this); alreadyDone = true; } } -mitk::Mapper::Pointer mitk::CoreObjectFactory::CreateMapper(mitk::DataNode *node, MapperSlotId id) +mitk::Mapper::Pointer mitk::CoreObjectFactory::GetMapperFromServiceRegistry(DataNode *node, MapperSlotId id) { - mitk::Mapper::Pointer newMapper = nullptr; - mitk::Mapper::Pointer tmpMapper = nullptr; - - // check whether extra factories provide mapper - for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) - { - tmpMapper = (*it)->CreateMapper(node, id); - if (tmpMapper.IsNotNull()) - newMapper = tmpMapper; - } - + Mapper::Pointer newMapper = nullptr; // Try getting a service - if (newMapper.IsNull() && node->GetData() != nullptr) + if (node->GetData() != nullptr) { // service query - std::string filter = us::LDAPProp("PROP_SUPPORTED_DATA_TYPE_NAME") == node->GetData()->GetNameOfClass() && - us::LDAPProp("PROP_SUPPORTED_SLOT_ID") == id; + std::string filter = + us::LDAPProp("PROP_DATA_TYPE_NAME") == node->GetData()->GetNameOfClass() && us::LDAPProp("PROP_SLOT_ID") == id; auto refs = us::GetModuleContext()->GetServiceReferences(filter); // service ranking us::ServiceReference highestRankedRef; int highestPriority = 0; for (auto ref : refs) { if (ref.GetProperty("PROP_PRIORITY").Type() == typeid(int)) { int refPriority = us::any_cast(ref.GetProperty("PROP_PRIORITY")); if (refPriority > highestPriority) { highestPriority = refPriority; highestRankedRef = ref; } } } - // service aquisition + // service aqcuisition try { // promised by the library to return false when invalid (default constructed) if (highestRankedRef) { - newMapper = us::GetModuleContext()->GetServiceObjects(highestRankedRef).GetService(); - newMapper->SetDataNode(node); + newMapper = GetMapperFromServiceRegistry(highestRankedRef, node); } } - catch (std::exception &e) + catch (const std::exception &e) { // Todo check for possible memory leak MITK_ERROR << "Tried getting a mapper service got: " << e.what(); newMapper = nullptr; } } + return newMapper; +} + +void mitk::CoreObjectFactory::UngetMapperFromServiceRegistry(Mapper *mapperService) +{ + auto iter = m_MapperServices.find(mapperService); + if (iter != m_MapperServices.end()) + { + iter->second.UngetService(mapperService); + m_MapperConsumers.find(iter->second.GetServiceReference())->second.erase(mapperService->GetDataNode()); + m_MapperServices.erase(iter); + } +} + +mitk::Mapper::Pointer mitk::CoreObjectFactory::CreateMapper(mitk::DataNode *node, MapperSlotId id) +{ + mitk::Mapper::Pointer newMapper = nullptr; + mitk::Mapper::Pointer tmpMapper = nullptr; + + // newMapper = GetMapperFromServiceRegistry(node, id); + + // check whether extra factories provide mapper + if (newMapper.IsNull()) + { + for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) + { + tmpMapper = (*it)->CreateMapper(node, id); + if (tmpMapper.IsNotNull()) + newMapper = tmpMapper; + } + } if (newMapper.IsNull()) { mitk::BaseData *data = node->GetData(); if (id == mitk::BaseRenderer::Standard2D) { if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::ImageVtkMapper2D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::PlaneGeometryDataMapper2D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::SurfaceVtkMapper2D::New(); // cast because SetDataNode is not virtual auto *castedMapper = dynamic_cast(newMapper.GetPointer()); castedMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::PointSetVtkMapper2D::New(); newMapper->SetDataNode(node); } } else if (id == mitk::BaseRenderer::Standard3D) { if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::PlaneGeometryDataVtkMapper3D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::SurfaceVtkMapper3D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::PointSetVtkMapper3D::New(); newMapper->SetDataNode(node); } } } return newMapper; } +mitk::Mapper::Pointer mitk::CoreObjectFactory::GetMapperFromServiceRegistry(us::ServiceReference ref, + DataNode *consumer) +{ + Mapper::Pointer newMapper = nullptr; + auto idAny = ref.GetProperty("PROP_SLOT_ID"); + int id = 0; + if (!ref || idAny.Type() != typeid(int)) + return newMapper; + + id = us::any_cast(idAny); + + auto iter = m_MapperServiceObjects.find(ref); + if (iter == m_MapperServiceObjects.end()) + { + MITK_INFO << "Fetched a fresh serviceObjects for " << ref; + m_MapperServiceObjects.insert(std::make_pair(ref, us::GetModuleContext()->GetServiceObjects(ref))); + + us::ServiceListener unregisterListener = + std::function([ this, id ](const us::ServiceEvent &e) -> auto { + MITK_INFO << "Received " << e.GetType(); + if (e.GetType() == us::ServiceEvent::UNREGISTERING) + { + auto ref = e.GetServiceReference(); + + auto consumerIter = m_MapperConsumers.find(ref); + if (m_MapperConsumers.end() != consumerIter) /*entry was found*/ + { + std::set nodeSet = consumerIter->second; + for (auto setIter = nodeSet.begin(); setIter != nodeSet.end(); /*increment by erase*/) + { + DataNode *node = *setIter; + if (nullptr != node) + { + node->SetMapper(id, nullptr); + } + // erase returns the iterator to the next object + setIter = nodeSet.erase(setIter); + } + m_MapperConsumers.erase(consumerIter); + } + if (m_MapperServiceObjects.find(ref) != m_MapperServiceObjects.end()) + { + m_MapperServiceObjects.erase(ref); + } + } + }); + us::GetModuleContext()->AddServiceListener( + unregisterListener, + us::LDAPProp("PROP_CLASS_NAME") == us::any_cast(ref.GetProperty("PROP_CLASS_NAME"))); + } + us::ServiceObjects serviceObjects = m_MapperServiceObjects.find(ref)->second; + newMapper = serviceObjects.GetService(); + + m_MapperServices.insert(std::make_pair(newMapper, serviceObjects)); + m_MapperConsumers[ref].insert(consumer); + newMapper->SetDataNode(consumer); + return newMapper; +} + const char *mitk::CoreObjectFactory::GetFileExtensions() { MultimapType aMap; for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) { aMap = (*it)->GetFileExtensionsMap(); this->MergeFileExtensions(m_FileExtensionsMap, aMap); } this->CreateFileExtensions(m_FileExtensionsMap, m_FileExtensions); return m_FileExtensions.c_str(); } void mitk::CoreObjectFactory::MergeFileExtensions(MultimapType &fileExtensionsMap, MultimapType inputMap) { std::pair pairOfIter; for (auto it = inputMap.begin(); it != inputMap.end(); ++it) { bool duplicateFound = false; pairOfIter = fileExtensionsMap.equal_range((*it).first); for (auto it2 = pairOfIter.first; it2 != pairOfIter.second; ++it2) { // cout << " [" << (*it).first << ", " << (*it).second << "]" << endl; std::string aString = (*it2).second; if (aString.compare((*it).second) == 0) { // cout << " DUP!! [" << (*it).first << ", " << (*it).second << "]" << endl; duplicateFound = true; break; } } if (!duplicateFound) { fileExtensionsMap.insert(std::pair((*it).first, (*it).second)); } } } mitk::CoreObjectFactoryBase::MultimapType mitk::CoreObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } void mitk::CoreObjectFactory::CreateFileExtensionsMap() { /* m_FileExtensionsMap.insert(std::pair("*.dcm", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.DCM", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.dc3", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.DC3", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.gdcm", "DICOM files")); m_FileExtensionsMap.insert(std::pair("*.seq", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.seq.gz", "DKFZ Pic")); m_FileExtensionsMap.insert(std::pair("*.dcm", "Sets of 2D slices")); m_FileExtensionsMap.insert(std::pair("*.gdcm", "Sets of 2D slices")); */ } const char *mitk::CoreObjectFactory::GetSaveFileExtensions() { MultimapType aMap; for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) { aMap = (*it)->GetSaveFileExtensionsMap(); this->MergeFileExtensions(m_SaveFileExtensionsMap, aMap); } this->CreateFileExtensions(m_SaveFileExtensionsMap, m_SaveFileExtensions); return m_SaveFileExtensions.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::CoreObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } mitk::CoreObjectFactory::FileWriterList mitk::CoreObjectFactory::GetFileWriters() { FileWriterList allWriters = m_FileWriters; // sort to merge lists later on typedef std::set FileWriterSet; FileWriterSet fileWritersSet; fileWritersSet.insert(allWriters.begin(), allWriters.end()); // collect all extra factories for (auto it = m_ExtraFactories.begin(); it != m_ExtraFactories.end(); ++it) { FileWriterList list2 = (*it)->GetFileWriters(); // add them to the sorted set fileWritersSet.insert(list2.begin(), list2.end()); } // write back to allWriters to return a list allWriters.clear(); allWriters.insert(allWriters.end(), fileWritersSet.begin(), fileWritersSet.end()); return allWriters; } void mitk::CoreObjectFactory::MapEvent(const mitk::Event *, const int) {} std::string mitk::CoreObjectFactory::GetDescriptionForExtension(const std::string &extension) { std::multimap fileExtensionMap = GetSaveFileExtensionsMap(); for (auto it = fileExtensionMap.begin(); it != fileExtensionMap.end(); ++it) if (it->first == extension) return it->second; return ""; // If no matching extension was found, return emtpy string } void mitk::CoreObjectFactory::RegisterLegacyReaders(mitk::CoreObjectFactoryBase *factory) { // We are not really interested in the string, just call the method since // many readers initialize the map the first time when this method is called factory->GetFileExtensions(); std::map> extensionsByCategories; std::multimap fileExtensionMap = factory->GetFileExtensionsMap(); for (auto it = fileExtensionMap.begin(); it != fileExtensionMap.end(); ++it) { std::string extension = it->first; // remove "*." extension = extension.erase(0, 2); extensionsByCategories[it->second].push_back(extension); } for (auto &extensionsByCategorie : extensionsByCategories) { m_LegacyReaders[factory].push_back( new mitk::LegacyFileReaderService(extensionsByCategorie.second, extensionsByCategorie.first)); } } void mitk::CoreObjectFactory::UnRegisterLegacyReaders(mitk::CoreObjectFactoryBase *factory) { auto iter = m_LegacyReaders.find(factory); if (iter != m_LegacyReaders.end()) { for (auto &elem : iter->second) { delete elem; } m_LegacyReaders.erase(iter); } } void mitk::CoreObjectFactory::RegisterLegacyWriters(mitk::CoreObjectFactoryBase *factory) { // Get all external Writers mitk::CoreObjectFactory::FileWriterList writers = factory->GetFileWriters(); // We are not really interested in the string, just call the method since // many writers initialize the map the first time when this method is called factory->GetSaveFileExtensions(); MultimapType fileExtensionMap = factory->GetSaveFileExtensionsMap(); for (auto it = writers.begin(); it != writers.end(); ++it) { std::vector extensions = (*it)->GetPossibleFileExtensions(); if (extensions.empty()) continue; std::string description; for (auto ext = extensions.begin(); ext != extensions.end(); ++ext) { if (ext->empty()) continue; std::string extension = *ext; std::string extensionWithStar = extension; if (extension.find_first_of('*') == 0) { // remove "*." extension = extension.substr(0, extension.size() - 2); } else { extensionWithStar.insert(extensionWithStar.begin(), '*'); } for (auto fileExtensionIter = fileExtensionMap.begin(); fileExtensionIter != fileExtensionMap.end(); ++fileExtensionIter) { if (fileExtensionIter->first == extensionWithStar) { description = fileExtensionIter->second; break; } } if (!description.empty()) break; } if (description.empty()) { description = std::string("Legacy ") + (*it)->GetNameOfClass() + " Reader"; } mitk::FileWriter::Pointer fileWriter(it->GetPointer()); mitk::LegacyFileWriterService *lfws = new mitk::LegacyFileWriterService(fileWriter, description); m_LegacyWriters[factory].push_back(lfws); } } void mitk::CoreObjectFactory::UnRegisterLegacyWriters(mitk::CoreObjectFactoryBase *factory) { auto iter = m_LegacyWriters.find(factory); if (iter != m_LegacyWriters.end()) { for (auto &elem : iter->second) { delete elem; } m_LegacyWriters.erase(iter); } }