diff --git a/Modules/Core/include/mitkCoreServices.h b/Modules/Core/include/mitkCoreServices.h index 7d619823d4..fa1830a448 100644 --- a/Modules/Core/include/mitkCoreServices.h +++ b/Modules/Core/include/mitkCoreServices.h @@ -1,173 +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 MITKCORESERVICES_H #define MITKCORESERVICES_H #include "MitkCoreExports.h" #include #include #include #include #include #include #include namespace mitk { struct IMimeTypeProvider; struct IShaderRepository; class IPropertyAliases; class IPropertyDescriptions; class IPropertyExtensions; class IPropertyFilters; class IPropertyPersistence; +class IAnnotationService; /** * @brief Access MITK core services. * * This class can be used to conveniently access common * MITK Core service objects. Some getter methods where implementations * exist in the core library are guaranteed to return a non-NULL service object. * * To ensure that CoreServices::Unget() is called after the caller * has finished using a service object, you should use the CoreServicePointer * helper class which calls Unget() when it goes out of scope: * * \code * CoreServicePointer shaderRepo(CoreServices::GetShaderRepository()); * // Do something with shaderRepo * \endcode * * @see CoreServicePointer */ class MITKCORE_EXPORT CoreServices { public: /** * @brief Get an IShaderRepository instance. * @param context The module context of the module getting the service. * @return A IShaderRepository instance which can be NULL. */ static IShaderRepository *GetShaderRepository(); /** * @brief Get an IPropertyAliases instance. * @param context The module context of the module getting the service. * @return A non-NULL IPropertyAliases instance. */ static IPropertyAliases *GetPropertyAliases(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyDescriptions instance. * @param context The module context of the module getting the service. * @return A non-NULL IPropertyDescriptions instance. */ static IPropertyDescriptions *GetPropertyDescriptions(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyExtensions instance. * @param context The module context of the module getting the service. * @return A non-NULL IPropertyExtensions instance. */ static IPropertyExtensions *GetPropertyExtensions(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyFilters instance. * @param context The module context of the module getting the service. * @return A non-NULL IPropertyFilters instance. */ static IPropertyFilters *GetPropertyFilters(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyPersistence instance. * @param context The module context of the module getting the service. * @return A non-NULL IPropertyPersistence instance. */ static IPropertyPersistence *GetPropertyPersistence(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IMimeTypeProvider instance. * @param context The module context of the module getting the service. * @return A non-NULL IMimeTypeProvider instance. */ static IMimeTypeProvider *GetMimeTypeProvider(us::ModuleContext *context = us::GetModuleContext()); /** + * @brief TODO19786 Get an IMimeTypeProvider instance. + * @param context The module context of the module getting the service. + * @return A non-NULL IMimeTypeProvider instance. + */ + static IAnnotationService* GetAnnotationService(us::ModuleContext* context = us::GetModuleContext()); + + /** * @brief Unget a previously acquired service instance. * @param service The service instance to be released. * @return \c true if ungetting the service was successful, \c false otherwise. */ template static bool Unget(S *service, us::ModuleContext *context = us::GetModuleContext()) { return Unget(context, us_service_interface_iid(), service); } private: static bool Unget(us::ModuleContext *context, const std::string &interfaceId, void *service); // purposely not implemented CoreServices(); CoreServices(const CoreServices &); CoreServices &operator=(const CoreServices &); }; /** * @brief A RAII helper class for core service objects. * * This is class is intended for usage in local scopes; it calls * CoreServices::Unget(S*) in its destructor. You should not construct * multiple CoreServicePointer instances using the same service pointer, * unless it is retrieved by a new call to a CoreServices getter method. * * @see CoreServices */ template class MITK_LOCAL CoreServicePointer { public: explicit CoreServicePointer(S *service) : m_service(service) { assert(m_service); } ~CoreServicePointer() { try { CoreServices::Unget(m_service); } catch (const std::exception &e) { MITK_ERROR << e.what(); } catch (...) { MITK_ERROR << "Ungetting core service failed."; } } S *operator->() const { return m_service; } private: // purposely not implemented CoreServicePointer(const CoreServicePointer &); CoreServicePointer &operator=(const CoreServicePointer &); S *const m_service; }; } #endif // MITKCORESERVICES_H diff --git a/Modules/Core/src/mitkCoreActivator.cpp b/Modules/Core/src/mitkCoreActivator.cpp index ac2a072d41..71bc2f883f 100644 --- a/Modules/Core/src/mitkCoreActivator.cpp +++ b/Modules/Core/src/mitkCoreActivator.cpp @@ -1,457 +1,460 @@ /*=================================================================== 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 "mitkCoreActivator.h" // File IO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDicomSeriesReaderService.h" #include "mitkLegacyFileWriterService.h" #include #include #include // Micro Services #include #include #include #include #include #include #include #include #include #include // ITK "injects" static initialization code for IO factories // via the itkImageIOFactoryRegisterManager.h header (which // is generated in the application library build directory). // To ensure that the code is called *before* the CppMicroServices // static initialization code (which triggers the Activator::Start // method), we include the ITK header here. #include void HandleMicroServicesMessages(us::MsgType type, const char *msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string &programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for (int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } class ShaderRepositoryTracker : public us::ServiceTracker { public: ShaderRepositoryTracker() : Superclass(us::GetModuleContext()) {} virtual void Close() override { us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Close(); } virtual void Open() override { us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); Superclass::Open(); } private: typedef us::ServiceTracker Superclass; TrackedType AddingService(const ServiceReferenceType &reference) override { mitk::IShaderRepository *shaderRepo = Superclass::AddingService(reference); if (shaderRepo) { // Add all existing shaders from modules to the new shader repository. // If the shader repository is registered in a modules activator, the // GetLoadedModules() function call below will also return the module // which is currently registering the repository. The HandleModuleEvent // method contains code to avoid double registrations due to a fired // ModuleEvent::LOADED event after the activators Load() method finished. std::vector modules = us::ModuleRegistry::GetLoadedModules(); for (std::vector::const_iterator iter = modules.begin(), endIter = modules.end(); iter != endIter; ++iter) { this->AddModuleShaderToRepository(*iter, shaderRepo); } m_ShaderRepositories.push_back(shaderRepo); } return shaderRepo; } void RemovedService(const ServiceReferenceType & /*reference*/, TrackedType tracked) override { m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked), m_ShaderRepositories.end()); } void HandleModuleEvent(const us::ModuleEvent moduleEvent) { if (moduleEvent.GetType() == us::ModuleEvent::LOADED) { std::vector shaderRepos; for (std::map>>::const_iterator shaderMapIter = m_ModuleIdToShaderIds.begin(), shaderMapEndIter = m_ModuleIdToShaderIds.end(); shaderMapIter != shaderMapEndIter; ++shaderMapIter) { if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end()) { shaderRepos.push_back(shaderMapIter->first); } } AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos); } else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) { RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories); } } void AddModuleShadersToRepositories(us::Module *module, const std::vector &shaderRepos) { // search and load shader files std::vector shaderResources = module->FindResources("Shaders", "*.xml", true); for (std::vector::iterator i = shaderResources.begin(); i != shaderResources.end(); ++i) { if (*i) { us::ModuleResourceStream rs(*i); for (const auto &shaderRepo : shaderRepos) { int id = (shaderRepo)->LoadShader(rs, i->GetBaseName()); if (id >= 0) { m_ModuleIdToShaderIds[shaderRepo][module->GetModuleId()].push_back(id); } } rs.seekg(0, std::ios_base::beg); } } } void AddModuleShaderToRepository(us::Module *module, mitk::IShaderRepository *shaderRepo) { std::vector shaderRepos; shaderRepos.push_back(shaderRepo); this->AddModuleShadersToRepositories(module, shaderRepos); } void RemoveModuleShadersFromRepositories(us::Module *module, const std::vector &shaderRepos) { for (const auto &shaderRepo : shaderRepos) { std::map> &moduleIdToShaderIds = m_ModuleIdToShaderIds[shaderRepo]; std::map>::iterator shaderIdsIter = moduleIdToShaderIds.find(module->GetModuleId()); if (shaderIdsIter != moduleIdToShaderIds.end()) { for (std::vector::iterator idIter = shaderIdsIter->second.begin(); idIter != shaderIdsIter->second.end(); ++idIter) { (shaderRepo)->UnloadShader(*idIter); } moduleIdToShaderIds.erase(shaderIdsIter); } } } private: // Maps to each shader repository a map containing module ids and related // shader registration ids std::map>> m_ModuleIdToShaderIds; std::vector m_ShaderRepositories; }; class FixedNiftiImageIO : public itk::NiftiImageIO { public: /** Standard class typedefs. */ typedef FixedNiftiImageIO Self; typedef itk::NiftiImageIO Superclass; typedef itk::SmartPointer Pointer; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(FixedNiftiImageIO, Superclass) virtual bool SupportsDimension(unsigned long dim) override { return dim > 1 && dim < 5; } }; void MitkCoreActivator::Load(us::ModuleContext *context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); this->m_Context = context; // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } m_ShaderRepositoryTracker.reset(new ShaderRepositoryTracker); // m_RenderingManager = mitk::RenderingManager::New(); // context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); m_PropertyPersistence.reset(new mitk::PropertyPersistence); context->RegisterService(m_PropertyPersistence.get()); m_MimeTypeProvider.reset(new mitk::MimeTypeProvider); m_MimeTypeProvider->Start(); m_MimeTypeProviderReg = context->RegisterService(m_MimeTypeProvider.get()); + m_AnnotationService.reset(new mitk::AnnotationService); + context->RegisterService(m_AnnotationService.get()); + this->RegisterDefaultMimeTypes(); this->RegisterItkReaderWriter(); this->RegisterVtkReaderWriter(); // Add custom Reader / Writer Services m_FileReaders.push_back(new mitk::PointSetReaderService()); m_FileWriters.push_back(new mitk::PointSetWriterService()); m_FileReaders.push_back(new mitk::GeometryDataReaderService()); m_FileWriters.push_back(new mitk::GeometryDataWriterService()); m_FileReaders.push_back(new mitk::DicomSeriesReaderService()); m_FileReaders.push_back(new mitk::RawImageFileReaderService()); m_ShaderRepositoryTracker->Open(); /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ this->RegisterLegacyWriter(); } void MitkCoreActivator::Unload(us::ModuleContext *) { for (auto &elem : m_FileReaders) { delete elem; } for (auto &elem : m_FileWriters) { delete elem; } for (auto &elem : m_FileIOs) { delete elem; } for (auto &elem : m_LegacyWriters) { delete elem; } // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. // we need to close the internal service tracker of the // MimeTypeProvider class here. Otherwise it // would hold on to the ModuleContext longer than it is // actually valid. m_MimeTypeProviderReg.Unregister(); m_MimeTypeProvider->Stop(); for (std::vector::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(), iterEnd = m_DefaultMimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { delete *mimeTypeIter; } m_ShaderRepositoryTracker->Close(); } void MitkCoreActivator::RegisterDefaultMimeTypes() { // Register some default mime-types std::vector mimeTypes = mitk::IOMimeTypes::Get(); for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { m_DefaultMimeTypes.push_back(*mimeTypeIter); m_Context->RegisterService(m_DefaultMimeTypes.back()); } } void MitkCoreActivator::RegisterItkReaderWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase"); for (auto &allobject : allobjects) { itk::ImageIOBase *io = dynamic_cast(allobject.GetPointer()); // NiftiImageIO does not provide a correct "SupportsDimension()" methods // and the supported read/write extensions are not ordered correctly if (dynamic_cast(io)) continue; // Use a custom mime-type for GDCMImageIO below if (dynamic_cast(allobject.GetPointer())) { // MITK provides its own DICOM reader (which internally uses GDCMImageIO). continue; } if (io) { m_FileIOs.push_back(new mitk::ItkImageIO(io)); } else { MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << (allobject)->GetNameOfClass(); } } FixedNiftiImageIO::Pointer itkNiftiIO = FixedNiftiImageIO::New(); mitk::ItkImageIO *niftiIO = new mitk::ItkImageIO(mitk::IOMimeTypes::NIFTI_MIMETYPE(), itkNiftiIO.GetPointer(), 0); m_FileIOs.push_back(niftiIO); } void MitkCoreActivator::RegisterVtkReaderWriter() { m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO()); m_FileIOs.push_back(new mitk::SurfaceStlIO()); m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO()); m_FileIOs.push_back(new mitk::ImageVtkXmlIO()); m_FileIOs.push_back(new mitk::ImageVtkLegacyIO()); } void MitkCoreActivator::RegisterLegacyWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter"); for (std::list::iterator i = allobjects.begin(); i != allobjects.end(); ++i) { mitk::FileWriter::Pointer io = dynamic_cast(i->GetPointer()); if (io) { std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Writer"; mitk::IFileWriter *writer = new mitk::LegacyFileWriterService(io, description); m_LegacyWriters.push_back(writer); } else { MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl; } } } US_EXPORT_MODULE_ACTIVATOR(MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE diff --git a/Modules/Core/src/mitkCoreServices.cpp b/Modules/Core/src/mitkCoreServices.cpp index 747be918c1..94b87e5c81 100644 --- a/Modules/Core/src/mitkCoreServices.cpp +++ b/Modules/Core/src/mitkCoreServices.cpp @@ -1,134 +1,140 @@ /*=================================================================== 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 "mitkCoreServices.h" #include #include #include #include #include #include #include +#include #include #include #include #include #include #include namespace mitk { itk::SimpleFastMutexLock &s_ContextToServicesMapMutex() { static itk::SimpleFastMutexLock mutex; return mutex; } std::map> &s_ContextToServicesMap() { static std::map> serviceMap; return serviceMap; } template static S *GetCoreService(us::ModuleContext *context) { if (context == NULL) context = us::GetModuleContext(); S *coreService = NULL; us::ServiceReference serviceRef = context->GetServiceReference(); if (serviceRef) { coreService = context->GetService(serviceRef); } assert(coreService && "Asserting non-NULL MITK core service"); { itk::MutexLockHolder l(s_ContextToServicesMapMutex()); s_ContextToServicesMap()[context].insert(std::make_pair(coreService, serviceRef)); } return coreService; } IShaderRepository *CoreServices::GetShaderRepository() { static us::ServiceTracker tracker(us::GetModuleContext()); tracker.Open(); return tracker.GetService(); } IPropertyAliases *CoreServices::GetPropertyAliases(us::ModuleContext *context) { return GetCoreService(context); } IPropertyDescriptions *CoreServices::GetPropertyDescriptions(us::ModuleContext *context) { return GetCoreService(context); } IPropertyExtensions *CoreServices::GetPropertyExtensions(us::ModuleContext *context) { return GetCoreService(context); } IPropertyFilters *CoreServices::GetPropertyFilters(us::ModuleContext *context) { return GetCoreService(context); } IPropertyPersistence *CoreServices::GetPropertyPersistence(us::ModuleContext *context) { return GetCoreService(context); } IMimeTypeProvider *CoreServices::GetMimeTypeProvider(us::ModuleContext *context) { return GetCoreService(context); } +IAnnotationService* CoreServices::GetAnnotationService(us::ModuleContext* context) +{ + return GetCoreService(context); +} + bool CoreServices::Unget(us::ModuleContext *context, const std::string & /*interfaceId*/, void *service) { bool success = false; itk::MutexLockHolder l(s_ContextToServicesMapMutex()); std::map>::iterator iter = s_ContextToServicesMap().find(context); if (iter != s_ContextToServicesMap().end()) { std::map::iterator iter2 = iter->second.find(service); if (iter2 != iter->second.end()) { us::ServiceReferenceU serviceRef = iter2->second; if (serviceRef) { success = context->UngetService(serviceRef); if (success) { iter->second.erase(iter2); } } } } return success; } }