diff --git a/Core/Code/IO/mitkAbstractFileReader.cpp b/Core/Code/IO/mitkAbstractFileReader.cpp index 411e83bd99..e64b64d364 100644 --- a/Core/Code/IO/mitkAbstractFileReader.cpp +++ b/Core/Code/IO/mitkAbstractFileReader.cpp @@ -1,414 +1,414 @@ /*=================================================================== 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 namespace mitk { AbstractFileReader::InputStream::InputStream(IFileReader* reader, std::ios_base::openmode mode) : std::istream(NULL) , m_Stream(NULL) { std::istream* stream = reader->GetInputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileReader::InputStream::~InputStream() { delete m_Stream; } class AbstractFileReader::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase() , m_Stream(NULL) , m_PrototypeFactory(NULL) {} Impl(const Impl& other) : FileReaderWriterBase(other) , m_Stream(NULL) , m_PrototypeFactory(NULL) {} std::string m_Location; std::string m_TmpFile; std::istream* m_Stream; us::PrototypeServiceFactory* m_PrototypeFactory; us::ServiceRegistration m_Reg; }; AbstractFileReader::AbstractFileReader() : d(new Impl) { } AbstractFileReader::~AbstractFileReader() { UnregisterService(); delete d->m_PrototypeFactory; if (!d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); } } AbstractFileReader::AbstractFileReader(const AbstractFileReader& other) : IFileReader(), d(new Impl(*other.d.get())) { } AbstractFileReader::AbstractFileReader(const CustomMimeType& mimeType, const std::string& description) : d(new Impl) { d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Reading ///////////////////////// std::vector AbstractFileReader::Read() { std::vector result; DataStorage::Pointer ds = StandaloneDataStorage::New().GetPointer(); this->Read(*ds); DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll(); for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(), iterEnd = dataNodes->End(); iter != iterEnd; ++iter) { result.push_back(iter.Value()->GetData()); } return result; } DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage& ds) { DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New(); std::vector data = this->Read(); for (std::vector::iterator iter = data.begin(); iter != data.end(); ++iter) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); this->SetDefaultDataNodeProperties(node, this->GetInputLocation()); ds.Add(node); result->InsertElement(result->Size(), node); } return result; } IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const { if (d->m_Stream) { if (*d->m_Stream) return Supported; } else { if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true)) { return Supported; } } return Unsupported; } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext* context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if(context == NULL) { context = us::GetModuleContext(); } d->RegisterMimeType(context); if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering reader due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileReader* const m_Prototype; PrototypeFactory(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); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileReader::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception&) {} } us::ServiceProperties AbstractFileReader::GetServiceProperties() const { us::ServiceProperties result; result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription(); result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); return result; } us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext* context) { return d->RegisterMimeType(context); } void AbstractFileReader::SetMimeType(const CustomMimeType& mimeType) { d->SetMimeType(mimeType); } void AbstractFileReader::SetDescription(const std::string& description) { d->SetDescription(description); } void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); } int AbstractFileReader::GetRanking() const { return d->GetRanking(); } std::string AbstractFileReader::GetLocalFileName() const { std::string localFileName; if (d->m_Stream) { if (d->m_TmpFile.empty()) { // write the stream contents to temporary file std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation()); std::ofstream tmpStream; localFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext); tmpStream << d->m_Stream->rdbuf(); d->m_TmpFile = localFileName; } else { localFileName = d->m_TmpFile; } } else { localFileName = d->m_Location; } return localFileName; } //////////////////////// Options /////////////////////// void AbstractFileReader::SetDefaultOptions(const IFileReader::Options& defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); } void AbstractFileReader::SetInput(const std::string& location) { d->m_Location = location; d->m_Stream = NULL; } void AbstractFileReader::SetInput(const std::string& location, std::istream* is) { if (d->m_Stream != is && !d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); d->m_TmpFile.clear(); } d->m_Location = location; d->m_Stream = is; } std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; } std::istream*AbstractFileReader::GetInputStream() const { return d->m_Stream; } MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileReader::GetOption(const std::string& name) const { return d->GetOption(name); } void AbstractFileReader::SetOptions(const Options& options) { d->SetOptions(options); } void AbstractFileReader::SetOption(const std::string& name, const us::Any& value) { d->SetOption(name, value); } ////////////////// MISC ////////////////// void AbstractFileReader::AddProgressCallback(const ProgressCallback& callback) { d->AddProgressCallback(callback); } void AbstractFileReader::RemoveProgressCallback(const ProgressCallback& callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// const CustomMimeType* AbstractFileReader::GetMimeType() const { return d->GetMimeType(); } void AbstractFileReader::SetMimeTypePrefix(const std::string& prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); } void AbstractFileReader::SetDefaultDataNodeProperties(DataNode* node, const std::string& filePath) { // path if (!filePath.empty()) { mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New( itksys::SystemTools::GetFilenamePath(filePath) ); node->SetProperty(StringProperty::PATH, pathProp); } // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); if(nameProp.IsNull() || (strcmp(nameProp->GetValue(),"No Name!")==0)) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer() ); if(baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(),"No Name!")==0)) { // name neither defined in node, nor in BaseData -> name = filebasename; - nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(itksys::SystemTools::GetFilenameName(filePath))); + nameProp = mitk::StringProperty::New( this->GetMimeType()->GetFilenameWithoutExtension(filePath) ); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if(!node->GetProperty("visible")) { node->SetVisibility(true); } } } diff --git a/Core/Code/IO/mitkCustomMimeType.cpp b/Core/Code/IO/mitkCustomMimeType.cpp index cb938e0f0b..fca265ac1e 100644 --- a/Core/Code/IO/mitkCustomMimeType.cpp +++ b/Core/Code/IO/mitkCustomMimeType.cpp @@ -1,185 +1,210 @@ /*=================================================================== 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 "mitkCustomMimeType.h" #include "mitkMimeType.h" #include +#include + namespace mitk { class FindCaseInsensitive { public: FindCaseInsensitive(std::string value) { lcValue.resize(value.size()); std::transform(value.begin(), value.end(), lcValue.begin(), ::tolower); } bool operator()(std::string elem) { std::transform(elem.begin(), elem.end(), elem.begin(), ::tolower); return elem == lcValue; } private: std::string lcValue; }; struct CustomMimeType::Impl { std::string m_Name; std::string m_Category; std::vector m_Extensions; std::string m_Comment; }; CustomMimeType::~CustomMimeType() { delete d; } CustomMimeType::CustomMimeType() : d(new Impl) { } CustomMimeType::CustomMimeType(const std::string& name) : d(new Impl) { d->m_Name = name; } CustomMimeType::CustomMimeType(const CustomMimeType& other) : d(new Impl(*other.d)) { } CustomMimeType::CustomMimeType(const MimeType& other) : d(new Impl) { d->m_Name = other.GetName(); d->m_Category = other.GetCategory(); d->m_Extensions = other.GetExtensions(); d->m_Comment = other.GetComment(); } CustomMimeType& CustomMimeType::operator=(const CustomMimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } CustomMimeType&CustomMimeType::operator=(const MimeType& other) { CustomMimeType tmp(other); Swap(tmp); return *this; } std::string CustomMimeType::GetName() const { return d->m_Name; } std::string CustomMimeType::GetCategory() const { return d->m_Category; } std::vector CustomMimeType::GetExtensions() const { return d->m_Extensions; } std::string CustomMimeType::GetComment() const { if (!d->m_Comment.empty()) return d->m_Comment; if (!d->m_Extensions.empty()) { return d->m_Extensions.front() + " File"; } return "Unknown"; } bool CustomMimeType::AppliesTo(const std::string& path) const +{ + std::string extension,filename; + return ParsePathForExtension(path,extension,filename); +} + +std::string CustomMimeType::GetExtension(const std::string& path) const +{ + std::string extension,filename; + ParsePathForExtension(path,extension,filename); + return extension; +} + +std::string CustomMimeType::GetFilenameWithoutExtension(const std::string& path) const +{ + std::string extension,filename; + ParsePathForExtension(path,extension,filename); + return filename; +} + +bool CustomMimeType::ParsePathForExtension(const std::string& path, std::string& extension, std::string& filename ) const { for (std::vector::const_iterator iter = d->m_Extensions.begin(), - iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter) + iterEnd = d->m_Extensions.end(); iter != iterEnd; ++iter) { if (!iter->empty() && path.size() >= iter->size()) { FindCaseInsensitive cmp(*iter); if (cmp(path.substr(path.size() - iter->size()))) { + extension = "." + *iter; + std::string filenameWithExtension = itksys::SystemTools::GetFilenameName(path); + filename = filenameWithExtension.substr(0,filenameWithExtension.size() - extension.size()); return true; } } } return false; } void CustomMimeType::SetName(const std::string& name) { d->m_Name = name; } void CustomMimeType::SetCategory(const std::string& category) { d->m_Category = category; } void CustomMimeType::SetExtension(const std::string& extension) { d->m_Extensions.clear(); d->m_Extensions.push_back(extension); } void CustomMimeType::AddExtension(const std::string& extension) { if (std::find_if(d->m_Extensions.begin(), d->m_Extensions.end(), FindCaseInsensitive(extension)) == d->m_Extensions.end()) { d->m_Extensions.push_back(extension); } } void CustomMimeType::SetComment(const std::string& comment) { d->m_Comment = comment; } void CustomMimeType::Swap(CustomMimeType& r) { Impl* d1 = d; d = r.d; r.d = d1; } CustomMimeType* CustomMimeType::Clone() const { return new CustomMimeType(*this); } void swap(CustomMimeType& l, CustomMimeType& r) { l.Swap(r); } } diff --git a/Core/Code/IO/mitkCustomMimeType.h b/Core/Code/IO/mitkCustomMimeType.h index 66e984b445..b2692f4506 100644 --- a/Core/Code/IO/mitkCustomMimeType.h +++ b/Core/Code/IO/mitkCustomMimeType.h @@ -1,85 +1,102 @@ /*=================================================================== 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 MITKCUSTOMMIMETYPE_H #define MITKCUSTOMMIMETYPE_H #include #include #include #include namespace mitk { class MimeType; /** * @ingroup IO * @ingroup MicroServices_Interfaces * * @brief The CustomMimeType class represents a custom mime-type which * may be registered as a service object. * * Instances of this class are usually created and registered as a service. * They wire files to specific IFileReader instances and provide data format * meta-data for selecting compatible IFileWriter instances. */ class MITK_CORE_EXPORT CustomMimeType { public: CustomMimeType(); CustomMimeType(const std::string& name); CustomMimeType(const CustomMimeType& other); explicit CustomMimeType(const MimeType& other); virtual ~CustomMimeType(); CustomMimeType& operator=(const CustomMimeType& other); CustomMimeType& operator=(const MimeType& other); std::string GetName() const; std::string GetCategory() const; std::vector GetExtensions() const; std::string GetComment() const; virtual bool AppliesTo(const std::string& path) const; + /** + * \brief Provides the first matching extension + * + * Checks whether any of its extensions are present at the end of the provided path. + * Returns the first found one. + */ + std::string GetExtension(const std::string& path) const; + /** + * \brief Provides the filename minus the extension + * + * Checks whether any of its extensions are present at the end of the provided path. + * Returns the filename without that extension and without the directory. + */ + std::string GetFilenameWithoutExtension(const std::string& path) const; void SetName(const std::string& name); void SetCategory(const std::string& category); void SetExtension(const std::string& extension); void AddExtension(const std::string& extension); void SetComment(const std::string& comment); void Swap(CustomMimeType& r); virtual CustomMimeType* Clone() const; private: + // returns true if an extension was found + bool ParsePathForExtension(const std::string& path, std::string& extension, std::string& filename ) const; + struct Impl; Impl* d; }; void swap(CustomMimeType& l, CustomMimeType& r); } MITK_DECLARE_SERVICE_INTERFACE(mitk::CustomMimeType, "org.mitk.CustomMimeType") #endif // MITKCUSTOMMIMETYPE_H