diff --git a/Core/Code/IO/mitkAbstractFileReader.cpp b/Core/Code/IO/mitkAbstractFileReader.cpp index f981bb0f6a..a0b6bb7fe6 100644 --- a/Core/Code/IO/mitkAbstractFileReader.cpp +++ b/Core/Code/IO/mitkAbstractFileReader.cpp @@ -1,161 +1,177 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include +#include + #include #include #include #include #include mitk::AbstractFileReader::AbstractFileReader() : m_Priority (0) , m_PrototypeFactory(NULL) { } mitk::AbstractFileReader::~AbstractFileReader() { delete m_PrototypeFactory; } mitk::AbstractFileReader::AbstractFileReader(const mitk::AbstractFileReader& other) : m_Extension(other.m_Extension) , m_Description(other.m_Description) , m_Priority(other.m_Priority) , m_Options(other.m_Options) , m_PrototypeFactory(NULL) { } mitk::AbstractFileReader::AbstractFileReader(const std::string& extension, const std::string& description) : m_Extension (extension) , m_Description (description) , m_Priority (0) , m_PrototypeFactory(NULL) { } ////////////////////// Reading ///////////////////////// std::list< itk::SmartPointer > mitk::AbstractFileReader::Read(const std::string& path, mitk::DataStorage* /*ds*/) { if (! itksys::SystemTools::FileExists(path.c_str())) mitkThrow() << "File '" + path + "' not found."; std::ifstream stream; stream.open(path.c_str()); return this->Read(stream); } +std::list< itk::SmartPointer > mitk::AbstractFileReader::Read(const std::istream& stream, mitk::DataStorage* ds) +{ + // Create a temporary file and copy the data to it + std::ofstream tmpOutputStream; + std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpOutputStream); + tmpOutputStream << stream.rdbuf(); + tmpOutputStream.close(); + + // Now read from the temporary file + std::list< itk::SmartPointer > result = this->Read(tmpFilePath, ds); + std::remove(tmpFilePath.c_str()); + return result; +} + //////////// µS Registration & Properties ////////////// us::ServiceRegistration mitk::AbstractFileReader::RegisterService(us::ModuleContext* context) { if (m_PrototypeFactory) return us::ServiceRegistration(); struct PrototypeFactory : public us::PrototypeServiceFactory { mitk::AbstractFileReader* const m_Prototype; PrototypeFactory(mitk::AbstractFileReader* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); return context->RegisterService(m_PrototypeFactory, props); } us::ServiceProperties mitk::AbstractFileReader::GetServiceProperties() { if ( m_Extension.empty() ) MITK_WARN << "Registered a Reader with no extension defined (m_Extension is empty). Reader will not be found by calls from ReaderManager.)"; if ( m_Description.empty() ) MITK_WARN << "Registered a Reader with no description defined (m_Description is empty). Reader will have no human readable extension information in FileDialogs.)"; std::transform(m_Extension.begin(), m_Extension.end(), m_Extension.begin(), ::tolower); us::ServiceProperties result; result[mitk::IFileReader::PROP_EXTENSION] = m_Extension; result[mitk::IFileReader::PROP_DESCRIPTION] = m_Description; result[us::ServiceConstants::SERVICE_RANKING()] = m_Priority; for (mitk::IFileReader::OptionList::const_iterator it = m_Options.begin(); it != m_Options.end(); ++it) { if (it->second) result[it->first] = std::string("true"); else result[it->first] = std::string("false"); } return result; } //////////////////////// Options /////////////////////// mitk::IFileReader::OptionList mitk::AbstractFileReader::GetOptions() const { return m_Options; } void mitk::AbstractFileReader::SetOptions(const mitk::IFileReader::OptionList& options) { if (options.size() != m_Options.size()) MITK_WARN << "Number of set Options differs from Number of available Options, which is a sign of false usage. Please consult documentation"; m_Options = options; } ////////////////// MISC ////////////////// bool mitk::AbstractFileReader::CanRead(const std::string& path) const { // Default implementation only checks if extension is correct std::string pathEnd = path.substr( path.length() - m_Extension.length(), m_Extension.length() ); return (m_Extension == pathEnd); } float mitk::AbstractFileReader::GetProgress() const { // Default implementation always returns 1 (finished) return 1; } ////////////////// µS related Getters ////////////////// int mitk::AbstractFileReader::GetPriority() const { return m_Priority; } std::string mitk::AbstractFileReader::GetExtension() const { return m_Extension; } std::string mitk::AbstractFileReader::GetDescription() const { return m_Description; } diff --git a/Core/Code/IO/mitkAbstractFileWriter.cpp b/Core/Code/IO/mitkAbstractFileWriter.cpp index e9fb7d1df9..54fcc9d00a 100644 --- a/Core/Code/IO/mitkAbstractFileWriter.cpp +++ b/Core/Code/IO/mitkAbstractFileWriter.cpp @@ -1,171 +1,185 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include +#include #include #include #include #include #include mitk::AbstractFileWriter::AbstractFileWriter() : m_Priority (0) , m_PrototypeFactory(NULL) { } mitk::AbstractFileWriter::~AbstractFileWriter() { delete m_PrototypeFactory; } mitk::AbstractFileWriter::AbstractFileWriter(const mitk::AbstractFileWriter& other) : m_Extension(other.m_Extension) , m_BasedataType(other.m_BasedataType) , m_Description(other.m_Description) , m_Priority(other.m_Priority) , m_Options(other.m_Options) , m_PrototypeFactory(NULL) { } mitk::AbstractFileWriter::AbstractFileWriter(const std::string& basedataType, const std::string& extension, const std::string& description) : m_Extension (extension) , m_BasedataType(basedataType) , m_Description (description) , m_Priority (0) , m_PrototypeFactory(NULL) { } ////////////////////// Writing ///////////////////////// void mitk::AbstractFileWriter::Write(const BaseData* data, const std::string& path) { - if (! itksys::SystemTools::FileExists(path.c_str())) - mitkThrow() << "File '" + path + "' not found."; std::ofstream stream; stream.open(path.c_str()); this->Write(data, stream); } +void mitk::AbstractFileWriter::Write(const mitk::BaseData* data, std::ostream& stream) +{ + // Create a temporary file and write the data to it + std::ofstream tmpOutputStream; + std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpOutputStream); + this->Write(data, tmpFilePath); + tmpOutputStream.close(); + + // Now copy the contents + std::ifstream tmpInputStream(tmpFilePath.c_str(), std::ios_base::binary); + stream << tmpInputStream.rdbuf(); + tmpInputStream.close(); + std::remove(tmpFilePath.c_str()); +} + //////////// µS Registration & Properties ////////////// us::ServiceRegistration mitk::AbstractFileWriter::RegisterService(us::ModuleContext* context) { if (m_PrototypeFactory) return us::ServiceRegistration(); struct PrototypeFactory : public us::PrototypeServiceFactory { mitk::AbstractFileWriter* const m_Prototype; PrototypeFactory(mitk::AbstractFileWriter* prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/) { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module* /*module*/, const us::ServiceRegistrationBase& /*registration*/, const us::InterfaceMap& service) { delete us::ExtractInterface(service); } }; m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); return context->RegisterService(m_PrototypeFactory, props); } us::ServiceProperties mitk::AbstractFileWriter::GetServiceProperties() { if ( m_Extension.empty() ) MITK_WARN << "Registered a Writer with no extension defined (m_Extension is empty). Writer will not be found by calls from WriterManager.)"; if ( m_BasedataType.empty() ) MITK_WARN << "Registered a Writer with no BasedataType defined (m_BasedataType is empty). Writer will not be found by calls from WriterManager.)"; if ( m_Description.empty() ) MITK_WARN << "Registered a Writer with no description defined (m_Description is empty). Writer will have no human readable extension information in FileDialogs.)"; us::ServiceProperties result; result[mitk::IFileWriter::PROP_EXTENSION] = m_Extension; result[mitk::IFileWriter::PROP_DESCRIPTION] = m_Description; result[mitk::IFileWriter::PROP_BASEDATA_TYPE] = m_BasedataType; result[us::ServiceConstants::SERVICE_RANKING()] = m_Priority; for (mitk::IFileWriter::OptionList::const_iterator it = m_Options.begin(); it != m_Options.end(); ++it) { result[it->first] = std::string("true"); } return result; } //////////////////////// Options /////////////////////// mitk::IFileWriter::OptionList mitk::AbstractFileWriter::GetOptions() const { return m_Options; } void mitk::AbstractFileWriter::SetOptions(const OptionList& options) { if (options.size() != m_Options.size()) MITK_WARN << "Number of set Options differs from Number of available Options, which is a sign of false usage. Please consult documentation"; m_Options = options; } ////////////////// MISC ////////////////// bool mitk::AbstractFileWriter::CanWrite(const BaseData* data) const { // Default implementation only checks if basedatatype is correct std::string externalDataType = data->GetNameOfClass(); return (externalDataType == m_BasedataType); } float mitk::AbstractFileWriter::GetProgress() const { // Default implementation always returns 1 (finished) return 1; } ////////////////// µS related Getters ////////////////// int mitk::AbstractFileWriter::GetPriority() const { return m_Priority; } std::string mitk::AbstractFileWriter::GetExtension() const { return m_Extension; } std::string mitk::AbstractFileWriter::GetDescription() const { return m_Description; } std::string mitk::AbstractFileWriter::GetSupportedBasedataType() const { return m_BasedataType; } diff --git a/Core/Code/IO/mitkFileReaderRegistry.cpp b/Core/Code/IO/mitkFileReaderRegistry.cpp index 84210eb685..fc19889a01 100644 --- a/Core/Code/IO/mitkFileReaderRegistry.cpp +++ b/Core/Code/IO/mitkFileReaderRegistry.cpp @@ -1,227 +1,228 @@ /*=================================================================== 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 "mitkFileReaderRegistry.h" // Microservices #include #include #include #include // Legacy Support #include //const std::string mitk::IFileWriter::PROP_EXTENSION = "org.mitk.services.FileWriter.Extension"; mitk::FileReaderRegistry::FileReaderRegistry() { } mitk::FileReaderRegistry::~FileReaderRegistry() { for (std::map >::iterator iter = m_ServiceObjects.begin(), end = m_ServiceObjects.end(); iter != end; ++iter) { iter->second.UngetService(iter->first); } } //////////////////// READING DIRECTLY //////////////////// std::list< mitk::BaseData::Pointer > mitk::FileReaderRegistry::Read(const std::string& path, us::ModuleContext* context) { // Find extension std::string extension = path; extension.erase(0, path.find_last_of('.')); // Get best Reader mitk::IFileReader* reader = GetReader(extension, context); // Throw exception if no compatible reader was found if (reader == NULL) mitkThrow() << "Tried to directly read a file of type '" + extension + "' via FileReaderRegistry, but no reader supporting this filetype was found."; return reader->Read(path); } -std::list< mitk::BaseData::Pointer > mitk::FileReaderRegistry::ReadAll(const std::list paths, std::list* unreadableFiles, - us::ModuleContext* context) +std::list< mitk::BaseData::Pointer > mitk::FileReaderRegistry::ReadAll( + const std::list& paths, std::list* unreadableFiles, + us::ModuleContext* context) { std::list< mitk::BaseData::Pointer > result; for (std::list::const_iterator iterator = paths.begin(), end = paths.end(); iterator != end; ++iterator) { try { std::list baseDataList = Read( *iterator, context ); result.merge(baseDataList); } catch (...) { if (unreadableFiles) unreadableFiles->push_back( *iterator ); } } return result; } //////////////////// GETTING READERS //////////////////// mitk::IFileReader* mitk::FileReaderRegistry::GetReader(const std::string& extension, us::ModuleContext* context ) { std::vector results = GetReaders(extension, context); if (results.empty()) return NULL; return results.front(); } std::vector mitk::FileReaderRegistry::GetReaders(const std::string& extension, us::ModuleContext* context ) { std::vector result; const std::vector > refs = GetReaderList(extension, context); result.reserve(refs.size()); // Translate List of ServiceRefs to List of Pointers for (std::vector >::const_iterator iter = refs.begin(), end = refs.end(); iter != end; ++iter) { us::ServiceObjects serviceObjects = context->GetServiceObjects(*iter); mitk::IFileReader* reader = serviceObjects.GetService(); m_ServiceObjects.insert(std::make_pair(reader, serviceObjects)); result.push_back(reader); } return result; } mitk::IFileReader* mitk::FileReaderRegistry::GetReader( const std::string& extension, const mitk::IFileReader::OptionNames& options, us::ModuleContext* context ) { std::vector matching = mitk::FileReaderRegistry::GetReaders(extension, options, context); if (matching.empty()) return NULL; return matching.front(); } std::vector mitk::FileReaderRegistry::GetReaders( const std::string& extension, const mitk::IFileReader::OptionNames& options, us::ModuleContext* context ) { const std::vector allReaders = mitk::FileReaderRegistry::GetReaders(extension, context); std::vector result; result.reserve(allReaders.size()); // the list is already sorted by priority. Now find reader that supports all options for (std::vector ::const_iterator iter = allReaders.begin(), end = allReaders.end(); iter != end; ++iter) { mitk::IFileReader * currentReader = *iter; // Now see if this reader supports all options. If yes, push to results if ( mitk::FileReaderRegistry::ReaderSupportsOptions(currentReader, options) ) { result.push_back(currentReader); } } return result; } void mitk::FileReaderRegistry::UngetReader(mitk::IFileReader* reader) { std::map >::iterator readerIter = m_ServiceObjects.find(reader); if (readerIter != m_ServiceObjects.end()) { readerIter->second.UngetService(reader); m_ServiceObjects.erase(readerIter); } } void mitk::FileReaderRegistry::UngetReaders(const std::vector& readers) { for (std::vector::const_iterator iter = readers.begin(), end = readers.end(); iter != end; ++iter) { this->UngetReader(*iter); } } //////////////////// GENERIC INFORMATION //////////////////// std::string mitk::FileReaderRegistry::GetSupportedExtensions(const std::string& extension) { us::ModuleContext* context = us::GetModuleContext(); const std::vector > refs = GetReaderList(extension, context); std::vector entries; // Will contain Description + Extension (Human readable) entries.reserve(refs.size()); std::string knownExtensions; // Will contain plain list of all known extensions (for the QFileDialog entry "All Known Extensions") for (std::vector >::const_iterator iterator = refs.begin(), end = refs.end(); iterator != end; ++iterator) { // Generate List of Extensions if (iterator == refs.begin()) // First entry without semicolon knownExtensions += "*" + iterator->GetProperty(mitk::IFileReader::PROP_EXTENSION).ToString(); else // Ad semicolon for each following entry knownExtensions += "; *" + iterator->GetProperty(mitk::IFileReader::PROP_EXTENSION).ToString(); // Generate List of human readable entries composed of Description + Extension std::string entry = iterator->GetProperty(mitk::IFileReader::PROP_DESCRIPTION).ToString() + "(*" + iterator->GetProperty(mitk::IFileReader::PROP_EXTENSION).ToString() + ");;"; entries.push_back(entry); } std::sort(entries.begin(), entries.end()); std::string result = "Known Extensions (" + knownExtensions + ");;All (*)"; for (std::vector::const_iterator iterator = entries.begin(), end = entries.end(); iterator != end; ++iterator) { result += ";;" + *iterator; } return result; } //////////////////// INTERNAL CODE //////////////////// bool mitk::FileReaderRegistry::ReaderSupportsOptions(mitk::IFileReader* reader, const mitk::IFileReader::OptionNames& options ) { const mitk::IFileReader::OptionList readerOptions = reader->GetOptions(); if (options.empty()) return true; // if no options were requested, return true unconditionally if (readerOptions.empty()) return false; // if options were requested and reader supports no options, return false // For each of the strings in requested options, check if option is available in reader for(mitk::IFileReader::OptionNames::const_iterator options_i = options.begin(), i_end = options.end(); options_i != i_end; ++options_i) { { bool optionFound = false; // Iterate over each available option from reader to check if one of them matches the current option for(mitk::IFileReader::OptionList::const_iterator options_j = readerOptions.begin(), j_end = readerOptions.end(); options_j != j_end; ++options_j) { if ( *options_i == options_j->first ) optionFound = true; } if (optionFound == false) return false; // If one option was not found, leave method and return false } } return true; // if all options have been found, return true } //////////////////// uS-INTERACTION //////////////////// std::vector< us::ServiceReference > mitk::FileReaderRegistry::GetReaderList(const std::string& extension, us::ModuleContext* context ) { // filter for class and extension std::string filter; if (!extension.empty()) { filter = us::LDAPProp(mitk::IFileReader::PROP_EXTENSION) == extension; } std::vector > result = context->GetServiceReferences(filter); std::sort(result.begin(), result.end()); std::reverse(result.begin(), result.end()); return result; } diff --git a/Core/Code/IO/mitkFileReaderRegistry.h b/Core/Code/IO/mitkFileReaderRegistry.h index 9af2033c2d..bd649a8243 100644 --- a/Core/Code/IO/mitkFileReaderRegistry.h +++ b/Core/Code/IO/mitkFileReaderRegistry.h @@ -1,107 +1,107 @@ /*=================================================================== 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 FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 #define FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 #include #include #include // Microservices #include #include #include namespace mitk { /** * @ingroup Process * * Provides convenient access to mitk::IFileReader instances and reading * files into mitk::BaseData types. * * \note The life-time of all mitk::IFileReader objects returned by an * instance of this class ends with the destruction of that instance. */ class MITK_CORE_EXPORT FileReaderRegistry { public: FileReaderRegistry(); ~FileReaderRegistry(); /** * Reads the file located at path and returns the * contents as a DataNode. * * This method will select the best available reader in the service * registry for the task. * * UnsupportedFileException: If no compatible reader was found * FileNotFoundException: If no file was found at path * FileReadException: If the selected reader failed to read the file **/ std::list< itk::SmartPointer > Read(const std::string& path, us::ModuleContext* context = us::GetModuleContext()); - std::list< mitk::BaseData::Pointer > ReadAll(const std::list paths, std::list* unreadableFiles = 0, + std::list< mitk::BaseData::Pointer > ReadAll(const std::list& paths, std::list* unreadableFiles = 0, us::ModuleContext* context = us::GetModuleContext()); template itk::SmartPointer Read(const std::string& path, us::ModuleContext* context = us::GetModuleContext()) { std::list basedatas = Read(path, context); T* result = dynamic_cast (basedatas.front().GetPointer()); return result; } /** * Returns a compatible Reader to the given file extension **/ mitk::IFileReader* GetReader(const std::string& extension, us::ModuleContext* context = us::GetModuleContext() ); mitk::IFileReader* GetReader(const std::string& extension, const mitk::IFileReader::OptionNames& options, us::ModuleContext* context = us::GetModuleContext() ); std::vector GetReaders(const std::string& extension, us::ModuleContext* context = us::GetModuleContext() ); std::vector GetReaders(const std::string& extension, const mitk::IFileReader::OptionNames& options, us::ModuleContext* context = us::GetModuleContext() ); void UngetReader(mitk::IFileReader* reader); void UngetReaders(const std::vector& readers); std::string GetSupportedExtensions(const std::string& extension = ""); protected: std::vector< us::ServiceReference > GetReaderList(const std::string& extension, us::ModuleContext* context); bool ReaderSupportsOptions(mitk::IFileReader* reader, const mitk::IFileReader::OptionNames& options); private: // purposely not implemented FileReaderRegistry(const FileReaderRegistry&); FileReaderRegistry& operator=(const FileReaderRegistry&); std::map > m_ServiceObjects; }; } // namespace mitk #endif /* FileReaderRegistry_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Core/Code/IO/mitkLegacyFileWriterService.cpp b/Core/Code/IO/mitkLegacyFileWriterService.cpp index 8dfab80a78..892331e659 100644 --- a/Core/Code/IO/mitkLegacyFileWriterService.cpp +++ b/Core/Code/IO/mitkLegacyFileWriterService.cpp @@ -1,65 +1,58 @@ /*=================================================================== 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 mitk::LegacyFileWriterService::LegacyFileWriterService(mitk::FileWriter::Pointer legacyWriter, const std::string& basedataType, const std::string& extension, const std::string& description) : AbstractFileWriter(basedataType, extension, description) , m_LegacyWriter(legacyWriter) { if (extension.empty()) mitkThrow() << "LegacyFileWriterWrapper cannot be initialized without FileExtension." ; RegisterService(); } ////////////////////// Writing ///////////////////////// void mitk::LegacyFileWriterService::Write(const BaseData* data, const std::string& path) { if (m_LegacyWriter.IsNull()) mitkThrow() << "LegacyFileWriterService was incorrectly initialized: Has no LegacyFileWriter."; m_LegacyWriter->SetFileName(path.c_str()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(const_cast(data)); m_LegacyWriter->SetInput(node); m_LegacyWriter->Write(); } -void mitk::LegacyFileWriterService::Write(const BaseData* /*data*/, std::ostream& /*stream*/ ) +void mitk::LegacyFileWriterService::Write(const BaseData* data, std::ostream& stream) { - mitkThrow () << "Streaming is not supported in Legacy Wrappers."; - //return 0; -} - -bool mitk::LegacyFileWriterService::CanWrite(const BaseData* data) const -{ - std::string externalDataType = data->GetNameOfClass(); - return (externalDataType == m_BasedataType); + mitk::AbstractFileWriter::Write(data, stream); } mitk::LegacyFileWriterService* mitk::LegacyFileWriterService::Clone() const { return new LegacyFileWriterService(*this); } diff --git a/Core/Code/IO/mitkLegacyFileWriterService.h b/Core/Code/IO/mitkLegacyFileWriterService.h index 5c5e292074..077163dd18 100644 --- a/Core/Code/IO/mitkLegacyFileWriterService.h +++ b/Core/Code/IO/mitkLegacyFileWriterService.h @@ -1,61 +1,58 @@ /*=================================================================== 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 LegacyFileWriterService_H_HEADER_INCLUDED_C1E7E521 #define LegacyFileWriterService_H_HEADER_INCLUDED_C1E7E521 // Macro #include // MITK #include #include namespace mitk { //##Documentation //## @brief //## @ingroup Process class LegacyFileWriterService : public mitk::AbstractFileWriter { public: LegacyFileWriterService(mitk::FileWriter::Pointer legacyWriter, const std::string& basedataType, const std::string& extension, const std::string& description); using AbstractFileWriter::Write; virtual void Write(const BaseData* data, const std::string& path); virtual void Write(const BaseData* data, std::ostream& stream ); - virtual bool CanWrite(const BaseData* data) const; - - protected: mitk::FileWriter::Pointer m_LegacyWriter; private: LegacyFileWriterService* Clone() const; }; } // namespace mitk #endif /* LegacyFileWriterService_H_HEADER_INCLUDED_C1E7E521 */ diff --git a/Core/Code/Testing/mitkFileWriterManagerTest.cpp b/Core/Code/Testing/mitkFileWriterManagerTest.cpp index 9758d1ed17..70aaa50a34 100644 --- a/Core/Code/Testing/mitkFileWriterManagerTest.cpp +++ b/Core/Code/Testing/mitkFileWriterManagerTest.cpp @@ -1,230 +1,313 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include +#include +class DummyBaseData : public mitk::BaseData +{ +public: + + mitkClassMacro(DummyBaseData, mitk::BaseData) + itkNewMacro(Self) + + void SetRequestedRegion(const itk::DataObject * /*data*/) {} + void SetRequestedRegionToLargestPossibleRegion() {} + bool RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } + bool VerifyRequestedRegion() { return true; } +}; class DummyWriter : public mitk::AbstractFileWriter { public: DummyWriter(const DummyWriter& other) : mitk::AbstractFileWriter(other) + , m_Content("Hi there stream") { } DummyWriter(const std::string& basedataType, const std::string& extension, int priority) : mitk::AbstractFileWriter(basedataType, extension, "This is a dummy description") + , m_Content("Hi there stream") { m_Priority = priority; m_ServiceReg = this->RegisterService(); } ~DummyWriter() { if (m_ServiceReg) m_ServiceReg.Unregister(); } using AbstractFileWriter::Write; - virtual void Write(const mitk::BaseData* /*data*/, std::ostream& /*stream*/ ) - { } - - virtual void SetOptions(const std::list< std::string >& options ) + virtual void Write(const mitk::BaseData* data, std::ostream& stream) { - m_Options = options; - //m_Registration.SetProperties(ConstructServiceProperties()); + MITK_TEST_CONDITION_REQUIRED(dynamic_cast(data), "Correct data type") + stream << m_Content; } + std::string m_Content; + private: DummyWriter* Clone() const { return new DummyWriter(*this); } us::ServiceRegistration m_ServiceReg; }; // End of internal dummy Writer class DummyWriter2 : public mitk::AbstractFileWriter { public: DummyWriter2(const DummyWriter2& other) : mitk::AbstractFileWriter(other) + , m_Content("hi there file path") { } DummyWriter2(const std::string& basedataType, const std::string& extension, int priority) : mitk::AbstractFileWriter(basedataType, extension, "This is a dummy description") + , m_Content("hi there file path") { m_Priority = priority; m_ServiceReg = this->RegisterService(); } ~DummyWriter2() { if (m_ServiceReg) m_ServiceReg.Unregister(); } using AbstractFileWriter::Write; - virtual void Write(const mitk::BaseData* /*data*/, std::ostream& /*stream*/ ) - { } + virtual void Write(const mitk::BaseData* data, const std::string& filePath ) + { + MITK_TEST_CONDITION_REQUIRED(dynamic_cast(data), "Correct data type") + std::ofstream fileStream(filePath.c_str()); + fileStream << m_Content; + } + + virtual void Write(const mitk::BaseData* data, std::ostream& stream ) + { + mitk::AbstractFileWriter::Write(data, stream); + } - virtual void SetOptions(const std::list< std::string >& options ) + virtual bool CanWrite(const mitk::BaseData *data) const { - m_Options = options; - //m_Registration.SetProperties(ConstructServiceProperties()); + return dynamic_cast(data); } + std::string m_Content; + private: DummyWriter2* Clone() const { return new DummyWriter2(*this); } us::ServiceRegistration m_ServiceReg; }; // End of internal dummy Writer 2 + +void TestStreamMethods() +{ + DummyWriter dummyWriter(DummyBaseData::GetStaticNameOfClass(), ".stream", 100); + DummyWriter2 dummyWriter2(DummyBaseData::GetStaticNameOfClass(), ".file", 50); + mitk::FileWriterRegistry writerRegistry; + + // Test DummyWriter, which always uses a ostream for writing, even + // when a file path is used + DummyBaseData dummyData; + std::stringstream oss; + writerRegistry.Write(&dummyData, oss); + MITK_TEST_CONDITION_REQUIRED(dummyWriter.m_Content == oss.str(), "Dummy stream writer") + + std::string content; + { + std::ofstream tmpStream; + std::string tmpFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream); + writerRegistry.Write(&dummyData, tmpFileName); + + std::ifstream tmpInput(tmpFileName.c_str()); + std::getline(tmpInput, content); + tmpInput.close(); + tmpStream.close(); + std::remove(tmpFileName.c_str()); + } + MITK_TEST_CONDITION_REQUIRED(dummyWriter.m_Content == content, "Dummy stream writer") + + // Test DummyWriter2, which always uses a real file for writing, even + // when a std::ostream object is given + std::stringstream oss2; + dummyWriter2.Write(&dummyData, oss2); + MITK_TEST_CONDITION_REQUIRED(dummyWriter2.m_Content == oss2.str(), "Dummy 2 stream writer") + + std::string content2; + { + std::ofstream tmpStream; + std::string tmpFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream); + tmpStream.close(); + std::remove(tmpFileName.c_str()); + + // This is a work-around to get a temporary file name ending with ".file" + tmpFileName += ".file"; + writerRegistry.Write(&dummyData, tmpFileName); + + std::ifstream tmpInput(tmpFileName.c_str()); + std::getline(tmpInput, content2); + tmpInput.close(); + std::remove(tmpFileName.c_str()); + } + MITK_TEST_CONDITION_REQUIRED(dummyWriter2.m_Content == content2, "Dummy 2 stream writer") +} + /** * TODO */ int mitkFileWriterManagerTest(int argc , char* argv[]) { // always start with this! MITK_TEST_BEGIN("FileWriterManager"); + TestStreamMethods(); + + // mitk::FileWriterRegistry::Pointer frm = mitk::FileWriterRegistry::New(); // MITK_TEST_CONDITION_REQUIRED(argc == 2,"Testing FileWriterRegistry instantiation"); + DummyWriter testDR("testdata", "test", 1); DummyWriter otherDR("testdata", "other", 1); // MITK_TEST_CONDITION_REQUIRED(testDR->CanWrite("/this/is/a/folder/file.test"),"Positive test of default CanRead() implementation"); // MITK_TEST_CONDITION_REQUIRED(!testDR->CanWrite("/this/is/a/folder/file.tes"),"Negative test of default CanRead() implementation"); mitk::FileWriterRegistry* writerManager = new mitk::FileWriterRegistry; mitk::IFileWriter* returned = writerManager->GetWriter("", "test"); MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(testDR) != returned,"Testing correct retrieval of FileWriter 1/2"); returned = writerManager->GetWriter("", "other"); MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(otherDR) != returned,"Testing correct retrieval of FileWriter 2/2"); DummyWriter mediocreTestDR("testdata", "test", 20); DummyWriter prettyFlyTestDR("testdata", "test", 50); DummyWriter2 awesomeTestDR("testdata", "test", 100); returned = writerManager->GetWriter("test"); MITK_TEST_CONDITION_REQUIRED(dynamic_cast(&awesomeTestDR), "Testing correct priorized retrieval of FileWriter: Best Writer"); // Now to give those Writers some options, then we will try again mitk::IFileWriter::OptionList options; options.push_back(std::make_pair("isANiceGuy", true)); mediocreTestDR.SetOptions(options); options.clear(); options.push_back(std::make_pair("canFly", true)); prettyFlyTestDR.SetOptions(options); options.push_back(std::make_pair("isAwesome", true)); awesomeTestDR.SetOptions(options); //note: awesomeWriter canFly and isAwesome // Reset Options, use to define what we want the Writer to do mitk::IFileWriter::OptionNames optionFilter; optionFilter.push_back("canFly"); returned = writerManager->GetWriter("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(awesomeTestDR) != returned, "Testing correct retrieval of FileWriter with Options: Best Writer with options"); optionFilter.push_back("isAwesome"); returned = writerManager->GetWriter("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(awesomeTestDR) != returned, "Testing correct retrieval of FileWriter with multiple Options: Best Writer with options"); optionFilter.clear(); optionFilter.push_back("isANiceGuy"); returned = writerManager->GetWriter("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returned && &static_cast(mediocreTestDR) != returned, "Testing correct retrieval of specific FileWriter with Options: Low priority Writer with specific option"); optionFilter.push_back("canFly"); returned = writerManager->GetWriter("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returned == NULL, "Testing correct return of 0 value when no matching Writer was found"); // Onward to test the retrieval of multiple Writers std::vector< mitk::IFileWriter* > returnedList; returnedList = writerManager->GetWriters("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returnedList.empty(), "Testing correct return of zero Writers when no matching Writer was found, asking for all compatibles"); optionFilter.clear(); optionFilter.push_back("canFly"); returnedList = writerManager->GetWriters("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returnedList.size() == 2, "Testing correct return of two Writers when two matching Writer was found, asking for all compatibles"); MITK_TEST_CONDITION_REQUIRED(dynamic_cast(returnedList.front()), "Testing correct priorization of returned Writers with options 1/2"); optionFilter.clear(); optionFilter.push_back("isAwesome"); returnedList = writerManager->GetWriters("", "test", optionFilter); MITK_TEST_CONDITION_REQUIRED(returnedList.size() == 1, "Testing correct return of one Writers when one matching Writer was found, asking for all compatibles"); MITK_TEST_CONDITION_REQUIRED(dynamic_cast(returnedList.front()), "Testing correctness of result from former query"); mitk::CoreObjectFactory::GetInstance(); //mitk::FileReaderManager readerManager; //mitk::Image::Pointer image = readerManager.Read("F://Build//MITK-Data//Pic2DplusT.nrrd"); //writerManager->Write(image.GetPointer(), "F://Build//MITK-Data//Pic2DplusTcopy.nrrd"); //// And now to verify a working read chain for a mps file: //mitk::PointSetWriter::Pointer psr = mitk::PointSetWriter::New(); //mitk::BaseData::Pointer basedata; //basedata = mitk::FileWriterRegistry::Read("F://Build//MITK-Data//pointSet.mps"); //MITK_TEST_CONDITION_REQUIRED(basedata.IsNotNull(), "Testing correct read of PointSet"); //// Testing templated call to WriterManager //mitk::PointSet::Pointer pointset = mitk::FileWriterRegistry::Read< mitk::PointSet >("F://Build//MITK-Data//pointSet.mps"); //MITK_TEST_CONDITION_REQUIRED(pointset.IsNotNull(), "Testing templated call of Read()"); //// And now for something completely different... (Debug) //mitk::LegacyFileWriterService::Pointer lfr = mitk::LegacyFileWriterService::New(".nrrd", "Nearly Raw Raster Data"); //returned = mitk::FileWriterRegistry::GetWriter(".nrrd"); //MITK_TEST_CONDITION_REQUIRED(lfr == returned, "Testing correct retrieval of specific FileWriter with Options: Low priority Writer with specific option"); //mitk::BaseData::Pointer image = mitk::FileWriterRegistry::Read("F://Build//MITK-Data//Pic2DplusT.nrrd"); //MITK_TEST_CONDITION_REQUIRED(image.IsNotNull(), "Testing whether BaseData is empty or not"); //mitk::Image::Pointer image2 = dynamic_cast (image.GetPointer()); //MITK_TEST_CONDITION_REQUIRED(image2.IsNotNull(), "Testing if BaseData is an image"); // Delete this here because it will call the PrototypeServiceFactory::Unget() method // of the dummy writers. delete writerManager; //// always end with this! - MITK_TEST_END(); + MITK_TEST_END() }