diff --git a/Modules/AwesomeMapperService/CMakeLists.txt b/Modules/AwesomeMapperService/CMakeLists.txt index b51b3076bd..280c130bf5 100644 --- a/Modules/AwesomeMapperService/CMakeLists.txt +++ b/Modules/AwesomeMapperService/CMakeLists.txt @@ -1,5 +1,5 @@ MITK_CREATE_MODULE( # INCLUDE_DIRS . DEPENDS MitkCore - PACKAGE_DEPENDS + PACKAGE_DEPENDS ) \ No newline at end of file diff --git a/Modules/Core/include/mitkCoreObjectFactory.h b/Modules/Core/include/mitkCoreObjectFactory.h index d634079cc6..c5906e23ce 100644 --- a/Modules/Core/include/mitkCoreObjectFactory.h +++ b/Modules/Core/include/mitkCoreObjectFactory.h @@ -1,181 +1,155 @@ /*=================================================================== 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); /** * @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 53c644ed0e..ad45c89a7b 100644 --- a/Modules/Core/src/mitkCoreObjectFactory.cpp +++ b/Modules/Core/src/mitkCoreObjectFactory.cpp @@ -1,566 +1,437 @@ /*=================================================================== 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 "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::GetMapperFromServiceRegistry(DataNode *node, MapperSlotId id) -{ - Mapper::Pointer newMapper = nullptr; - // Try getting a service - if (node->GetData() != nullptr) - { - // service query - 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 aqcuisition - try - { - // promised by the library to return false when invalid (default constructed) - if (highestRankedRef) - { - newMapper = GetMapperFromServiceRegistry(highestRankedRef, node); - } - } - 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); } }